Skip to content

Add Majel's Place concept to Paddle #2091

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ RUN apt-get update && \
curl sed grep graphviz libjpeg-dev zlib1g-dev \
python-numpy python-matplotlib gcc g++ \
automake locales clang-format-3.8 swig doxygen cmake \
liblapack-dev liblapacke-dev \
liblapack-dev liblapacke-dev libboost-dev \
clang-3.8 llvm-3.8 libclang-3.8-dev && \
apt-get clean -y

Expand Down Expand Up @@ -61,6 +61,15 @@ RUN git clone https://github.com/woboq/woboq_codebrowser /woboq && \
-DCMAKE_BUILD_TYPE=Release . \
make)

# Install gtest.
#
# NOTE: This is added for quick hack of the development work of
# majel-in-paddle.
RUN git clone https://github.com/google/googletest /gtest && \
cd /gtest && \
git checkout -b release-1.8.0 && \
cmake . && make install

# Configure OpenSSH server. c.f. https://docs.docker.com/engine/examples/running_ssh_service
RUN mkdir /var/run/sshd
RUN echo 'root:root' | chpasswd
Expand Down
10 changes: 10 additions & 0 deletions majel/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CCFLAGS = -std=c++11 -I/work/paddle
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this PR is merged, I will add a CMakeLists.txt.

CC = nvcc

all : place_test

place.o : place.h place.cu
$(CC) $(CCFLAGS) -c place.cu -o $@

place_test : place.o place_test.cu
$(CC) $(CCFLAGS) -lgtest -lgtest_main $^ -o $@
61 changes: 61 additions & 0 deletions majel/place.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include <majel/place.h>

namespace majel {

namespace detail {

class PlacePrinter
: public boost::static_visitor<> {
private:
std::ostream& os_;
public:
PlacePrinter(std::ostream& os) : os_(os) {}

void operator()(const CpuPlace&) {
os_ << "CpuPlace";
}

void operator()(const GpuPlace& p) {
os_ << "GpuPlace(" << p.device << ")";
}
};

} // namespace majel

static Place the_default_place;

void set_place(const Place& place) {
the_default_place = place;
}

const Place& get_place() {
return the_default_place;
}

const GpuPlace default_gpu() {
return GpuPlace(0);
}

const CpuPlace default_cpu() {
return CpuPlace();
}

bool is_gpu_place(const Place& p) {
return boost::apply_visitor(IsGpuPlace(), p);
}

bool is_cpu_place(const Place& p) {
return !boost::apply_visitor(IsGpuPlace(), p);
}

bool places_are_same_class(const Place& p1, const Place& p2) {
return is_gpu_place(p1) == is_gpu_place(p2);
}

std::ostream& operator<<(std::ostream& os, const majel::Place& p) {
majel::detail::PlacePrinter printer(os);
boost::apply_visitor(printer, p);
return os;
}

} // namespace majel
50 changes: 50 additions & 0 deletions majel/place.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once
#include <boost/variant.hpp>
#include <iostream>

namespace majel {

struct CpuPlace {
CpuPlace() {} // WORKAROUND: for some reason, omitting this constructor
// causes errors with boost 1.59 and OSX
// needed for variant equality comparison
inline bool operator==(const CpuPlace&) const { return true; }

inline bool operator!=(const CpuPlace&) const { return false; }
};

struct GpuPlace {
GpuPlace(int d) : device(d) {}

// needed for variant equality comparison
inline bool operator==(const GpuPlace& o) const { return device == o.device; }

inline bool operator!=(const GpuPlace& o) const { return !(*this == o); }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the above "==" operation check equal as device == o.device, but here checks if it's the same instance?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right! Is Greg nearby and can you ask him about the problem?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, I thought *this is this. In this case, it's taking the neg of result from == operator.

Copy link
Contributor

@gangliao gangliao May 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wangkuiyi @helinwang I think it's correct. Because *this == o will trigger inline bool operator==(const GpuPlace& o) So it's still compare device id.


GpuPlace() : GpuPlace(0) {}
int device;
};

class IsGpuPlace : public boost::static_visitor<bool> {
public:
bool operator()(const CpuPlace&) const { return false; }

bool operator()(const GpuPlace& gpu) const { return true; }
};

typedef boost::variant<GpuPlace, CpuPlace> Place;

void set_place(const Place&);

const Place& get_place();

const GpuPlace default_gpu();
const CpuPlace default_cpu();

bool is_gpu_place(const Place&);
bool is_cpu_place(const Place&);
bool places_are_same_class(const Place&, const Place&);

std::ostream& operator<<(std::ostream&, const majel::Place&);

} // namespace majel
40 changes: 40 additions & 0 deletions majel/place_test.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "gtest/gtest.h"
#include "majel/place.h"
#include <sstream>

TEST(Place, Equality) {
majel::CpuPlace cpu;
majel::GpuPlace g0(0), g1(1), gg0(0);

EXPECT_EQ(cpu, cpu);
EXPECT_EQ(g0, g0);
EXPECT_EQ(g1, g1);
EXPECT_EQ(g0, gg0);

EXPECT_NE(g0, g1);

EXPECT_TRUE(majel::places_are_same_class(g0, gg0));
EXPECT_FALSE(majel::places_are_same_class(g0, cpu));
}

TEST(Place, Default) {
EXPECT_TRUE(majel::is_gpu_place( majel::get_place()));
EXPECT_TRUE(majel::is_gpu_place( majel::default_gpu()));
EXPECT_TRUE(majel::is_cpu_place( majel::default_cpu()));

majel::set_place(majel::CpuPlace());
EXPECT_TRUE(majel::is_cpu_place( majel::get_place()));
}

TEST(Place, Print) {
{
std::stringstream ss;
ss << majel::GpuPlace(1);
EXPECT_EQ("GpuPlace(1)", ss.str());
}
{
std::stringstream ss;
ss << majel::CpuPlace();
EXPECT_EQ("CpuPlace", ss.str());
}
}