Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion paddle/majel/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cc_library(majel SRCS place.cc)
cc_library(majel SRCS place.cc ddim.cc)
Copy link
Collaborator

Choose a reason for hiding this comment

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

According to our design, I believe that this line should be

cc_library(place SRCS place.cc)
cc_library(dim SRCS dim.cc)
cc_library(ddim SRCS ddim.cc DEPS dim)

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we need to add an optional OBJECT, because CMake add_library(name OBJECT source) can generate *.o

Copy link
Collaborator Author

@JiayiFeng JiayiFeng May 19, 2017

Choose a reason for hiding this comment

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

done.
But Dim is only a part of DDim, it is not an independent module and only has a dim.h file. So maybe these lines should be

cc_library(place SRCS place.cc)
cc_library(ddim SRCS ddim.cc)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Got it. Thanks!


if(WITH_TESTING)
add_subdirectory(test)
Expand Down
222 changes: 222 additions & 0 deletions paddle/majel/ddim.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
#include <majel/ddim.h>
Copy link
Collaborator

Choose a reason for hiding this comment

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

#include "paddle/majel/ddim.h"

  1. Please use double-quotes instead of angle-brackets, which is for system header files. More details at here: https://google.github.io/styleguide/cppguide.html#Names_and_Order_of_Includes

  2. Please make sure to use the full #include path. This makes sure that there is only one way to include each header file.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done


namespace majel {

///@cond HIDDEN

template <int i>
Dim<i> make_dim(const int* d) {
return Dim<i>(*d, make_dim<i - 1>(d + 1));
}

template <>
Dim<1> make_dim<1>(const int* d) {
return Dim<1>(*d);
}

void make_ddim(DDim& ddim, const int* dims, int n) {
switch (n) {
case 1:
ddim = make_dim<1>(dims);
break;
case 2:
ddim = make_dim<2>(dims);
break;
case 3:
ddim = make_dim<3>(dims);
break;
case 4:
ddim = make_dim<4>(dims);
break;
case 5:
ddim = make_dim<5>(dims);
break;
case 6:
ddim = make_dim<6>(dims);
break;
case 7:
ddim = make_dim<7>(dims);
break;
case 8:
ddim = make_dim<8>(dims);
break;
case 9:
ddim = make_dim<9>(dims);
break;
default:
throw std::invalid_argument(
"Dynamic dimensions must have between [1, 9] dimensions.");
}
}

///@endcond

DDim make_ddim(std::initializer_list<int> dims) {
DDim result(make_dim(0));
make_ddim(result, dims.begin(), dims.size());
return result;
}

DDim make_ddim(const std::vector<int>& dims) {
DDim result(make_dim(0));
make_ddim(result, &dims[0], dims.size());
return result;
}

///@cond HIDDEN
// XXX For some reason, putting this in an anonymous namespace causes errors
class DynamicMutableIndexer : public boost::static_visitor<int&> {
public:
DynamicMutableIndexer(int idx) : idx_(idx) {}

template <int D>
int& operator()(Dim<D>& dim) const {
return dim[idx_];
}

private:
int idx_;
};

class DynamicConstIndexer : public boost::static_visitor<int> {
public:
DynamicConstIndexer(int idx) : idx_(idx) {}

template <int D>
int operator()(const Dim<D>& dim) const {
return dim[idx_];
}

private:
int idx_;
};

///@endcond

int& DDim::operator[](int idx) {
return boost::apply_visitor(DynamicMutableIndexer(idx), var);
}

int DDim::operator[](int idx) const {
return boost::apply_visitor(DynamicConstIndexer(idx), var);
}

bool DDim::operator==(DDim d) const {
if (var.which() != d.getVar().which()) {
return false;
} else {
std::vector<int> v1 = vectorize(*this);
std::vector<int> v2 = vectorize(d);

for (unsigned int i = 0; i < v1.size(); i++) {
if (v1[i] != v2[i]) {
return false;
}
}

return true;
}
}

bool DDim::operator!=(DDim d) const { return !(*this == d); }

DDim DDim::operator+(DDim d) const {
std::vector<int> v1 = vectorize(*this);
std::vector<int> v2 = vectorize(d);

std::vector<int> v3;

assert(v1.size() == v2.size());
Copy link
Contributor

@gangliao gangliao May 18, 2017

Choose a reason for hiding this comment

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

Why not use the MAJEL_ASSERT directly?

Copy link
Collaborator Author

@JiayiFeng JiayiFeng May 18, 2017

Choose a reason for hiding this comment

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

According to util.h, MAJEL_ASSERT is available only in kernel code of Apple GPU. In other cases, we should use assert instead.


for (unsigned int i = 0; i < v1.size(); i++) {
v3.push_back(v1[i] + v2[i]);
}

return make_ddim(v3);
}

DDim DDim::operator*(DDim d) const {
std::vector<int> v1 = vectorize(*this);
std::vector<int> v2 = vectorize(d);

std::vector<int> v3;

assert(v1.size() == v2.size());

for (unsigned int i = 0; i < v1.size(); i++) {
v3.push_back(v1[i] * v2[i]);
}

return make_ddim(v3);
}

int get(const DDim& ddim, int idx) { return ddim[idx]; }

void set(DDim& ddim, int idx, int value) { ddim[idx] = value; }

///@cond HIDDEN
struct VectorizeVisitor : public boost::static_visitor<> {
std::vector<int>& vector;

VectorizeVisitor(std::vector<int>& v) : vector(v) {}

template <typename T>
void operator()(const T& t) {
vector.push_back(t.head);
this->operator()(t.tail);
}

void operator()(const Dim<1>& t) { vector.push_back(t.head); }
};
///@endcond

std::vector<int> vectorize(const DDim& ddim) {
std::vector<int> result;
VectorizeVisitor visitor(result);
boost::apply_visitor(visitor, ddim);
return result;
}

ssize_t product(const DDim& ddim) {
ssize_t result = 1;
std::vector<int> v = vectorize(ddim);
for (auto i : v) {
result *= i;
}
return result;
}

///\cond HIDDEN

struct ArityVisitor : boost::static_visitor<int> {
template <int D>
int operator()(Dim<D>) const {
return D;
}
};

///\endcond

int arity(const DDim& d) { return boost::apply_visitor(ArityVisitor(), d); }

///\cond HIDDEN

struct DDimPrinter : boost::static_visitor<void> {
std::ostream& os;
DDimPrinter(std::ostream& os_) : os(os_) {}

template <typename T>
void operator()(const T& t) {
os << t;
}
};

///\endcond

std::ostream& operator<<(std::ostream& os, const majel::DDim& ddim) {
DDimPrinter printer(os);
boost::apply_visitor(printer, ddim);
return os;
}

} // namespace majel
109 changes: 109 additions & 0 deletions paddle/majel/ddim.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#pragma once

#include <boost/variant.hpp>
#include <initializer_list>
#include <stdexcept>
#include <vector>

#include "majel/dim.h"

namespace majel {

namespace {
typedef boost::variant<Dim<1>,
Dim<2>,
Dim<3>,
Dim<4>,
Dim<5>,
Dim<6>,
Dim<7>,
Dim<8>,
Dim<9>>
DDimVar;
}

/**
* \brief A dynamically sized dimension.
*
* The number of dimensions must be between [1, 9].
*/
struct DDim {
DDimVar var;

DDim() : var(Dim<1>()) {}

template <int D>
DDim(const Dim<D>& in) : var(in) {}

template <int D>
DDim& operator=(const Dim<D>& in) {
var = in;
return *this;
}

int& operator[](int idx);
int operator[](int idx) const;

template <typename Visitor>
typename Visitor::result_type apply_visitor(Visitor& visitor) {
return var.apply_visitor(visitor);
}

template <typename Visitor>
typename Visitor::result_type apply_visitor(Visitor& visitor) const {
return var.apply_visitor(visitor);
}

DDimVar getVar() { return var; }

bool operator==(DDim d) const;

bool operator!=(DDim d) const;

DDim operator+(DDim d) const;

DDim operator*(DDim d) const;
};

/**
* \brief Make a DDim from std::vector<int>
*
* \param dims An vector of ints. Must be sized between [1, 9]
*/
DDim make_ddim(const std::vector<int>& dims);

/**
* \brief Make a DDim from an initializer list
*
* \param dims An initializer list of ints. Must be sized between [1, 9]
*
*/
DDim make_ddim(std::initializer_list<int> dims);

int get(const DDim& dim, int idx);
void set(DDim& dim, int idx, int val);

std::vector<int> vectorize(const DDim& ddim);

ssize_t product(const DDim& ddim);

/**
* \brief What is the length of this dimension?
*
* \param Dynamic dimension to inspect
*/

int arity(const DDim& ddim);

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

} // namespace majel

namespace boost {

template <typename T>
T get(const majel::DDim& in) {
return boost::get<T>(in.var);
}

} // namespace boost
Loading