提交 aef98218 编写于 作者: 朔-望's avatar 朔-望

update clang-format & update code stylee

上级 333ff13f
---
Language: Cpp
BasedOnStyle: LLVM
Standard: Cpp11
IndentWidth: 4
NamespaceIndentation: All
...
......@@ -6,6 +6,7 @@ repos:
files: (src).*\.(md|py|mm|swift|java|c|cc|cxx|cpp|cu|h|hpp|hxx)$
- id: remove-tabs
files: (src).*\.(md|py|mm|swift|java|c|cc|cxx|cpp|cu|h|hpp|hxx)$
- repo: https://github.com/pre-commit/pre-commit-hooks
sha: 5bf6c09bfa1297d3692cadd621ef95f1284e33c0
hooks:
......@@ -18,11 +19,21 @@ repos:
files: (src).*\.(md|py|mm|swift|java|c|cc|cxx|cpp|cu|h|hpp|hxx)$
- id: trailing-whitespace
files: (src).*\.(md|py|mm|swift|java|c|cc|cxx|cpp|cu|h|hpp|hxx)$
- repo: local
hooks:
- id: clang-format-with-version-check
name: clang-format
description: Format files with ClangFormat.
entry: bash .clang_format.hook -i
entry: bash ./tools/pre-commit.hooks/.clang_format.hook -i
language: system
files: (src).*\.(c|cc|cxx|cpp|h|hpp|hxx)$
#- repo: local
# hooks:
# - id: copyright_checker
# name: copyright_checker
# entry: python ./tools/pre-commit.hooks/.copyright.hook
# language: system
# files: (src).*\.(c|cc|cxx|cpp|cu|h|hpp|hxx|proto|py)$
# exclude: (?!.*third_party)^.*$ | (?!.*book)^.*$
......@@ -23,30 +23,31 @@ SOFTWARE.
namespace paddle_mobile {
namespace framework {
template <typename Dtype> class OperatorBase;
class OpDesc;
class BlockDesc;
class InferShapeContext;
}
namespace framework {
template <typename Dtype> class OperatorBase;
class OpDesc;
class BlockDesc;
class InferShapeContext;
}
using VariableNameMap = std::map<std::string, std::vector<std::string>>;
using VariableNameMap = std::map<std::string, std::vector<std::string>>;
template <typename Dtype>
using OpCreator = std::function<framework::OperatorBase<Dtype> *(
template <typename Dtype>
using OpCreator = std::function<framework::OperatorBase<Dtype> *(
const std::string & /*type*/, const VariableNameMap & /*inputs*/,
const VariableNameMap & /*outputs*/,
const framework::AttributeMap & /*attrs*/)>;
using GradOpMakerFN =
using GradOpMakerFN =
std::function<std::vector<std::unique_ptr<framework::OpDesc>>(
const framework::OpDesc &,
const std::unordered_set<std::string> & /*no_grad_set*/,
std::unordered_map<std::string, std::string> * /*grad_to_var*/,
const std::vector<framework::BlockDesc *> &grad_block)>;
using InferVarTypeFN = std::function<void(const framework::OpDesc & /*op_desc*/,
using InferVarTypeFN =
std::function<void(const framework::OpDesc & /*op_desc*/,
framework::BlockDesc * /*block*/)>;
using InferShapeFN = std::function<void(framework::InferShapeContext *)>;
using InferShapeFN = std::function<void(framework::InferShapeContext *)>;
};
......@@ -19,19 +19,19 @@ SOFTWARE.
#pragma once;
namespace paddle_mobile {
enum class Precision : int { FP32 = 0 };
enum class Precision : int { FP32 = 0 };
//! device type
enum DeviceTypeEnum { kINVALID = -1, kCPU = 0, kFPGA = 1, kGPU_MALI = 2 };
//! device type
enum DeviceTypeEnum { kINVALID = -1, kCPU = 0, kFPGA = 1, kGPU_MALI = 2 };
template <DeviceTypeEnum T> struct DeviceType {};
template <DeviceTypeEnum T> struct DeviceType {};
typedef DeviceType<kCPU> CPU;
typedef DeviceType<kFPGA> FPGA;
typedef DeviceType<kGPU_MALI> GPU_MALI;
typedef DeviceType<kCPU> CPU;
typedef DeviceType<kFPGA> FPGA;
typedef DeviceType<kGPU_MALI> GPU_MALI;
//! data type
enum DataType {
//! data type
enum DataType {
PM_INVALID = -1,
PM_HALF = 0,
PM_FLOAT = 1,
......@@ -47,9 +47,9 @@ enum DataType {
PM_BOOL = 11,
PM_SHAPE = 12,
PM_TENSOR = 13
};
//!
enum PMStatus {
};
//!
enum PMStatus {
PMSuccess = 0xFF, /*!< No errors */
PMNotInitialized = 0x01, /*!< Data not initialized. */
PMInvalidValue = 0x02, /*!< Incorrect variable value. */
......@@ -59,5 +59,5 @@ enum PMStatus {
PMOutOfMem = 0x06, /*!< OOM error*/
PMUnImplError = 0x07, /*!< Unimplement error. */
PMWrongDevice = 0x08 /*!< un-correct device. */
};
};
}
......@@ -21,9 +21,9 @@ SOFTWARE.
#pragma once
namespace paddle_mobile {
template <int ID, typename Type> struct IDToType { typedef Type type_t; };
template <int ID, typename Type> struct IDToType { typedef Type type_t; };
template <typename F, typename... Ts> struct VariantHelper {
template <typename F, typename... Ts> struct VariantHelper {
static const size_t size = sizeof(F) > VariantHelper<Ts...>::size
? sizeof(F)
: VariantHelper<Ts...>::size;
......@@ -35,9 +35,9 @@ template <typename F, typename... Ts> struct VariantHelper {
VariantHelper<Ts...>::Destroy(id, data);
}
}
};
};
template <typename F> struct VariantHelper<F> {
template <typename F> struct VariantHelper<F> {
static const size_t size = sizeof(F);
inline static void Destroy(size_t id, void *data) {
if (id == typeid(F).hash_code()) {
......@@ -46,19 +46,19 @@ template <typename F> struct VariantHelper<F> {
// std::cout << "未匹配到 " << std::endl;
}
}
};
};
template <size_t size> class RawData {
public:
template <size_t size> class RawData {
public:
char data[size];
RawData() {}
RawData(const RawData &raw_data) { strcpy(data, raw_data.data); }
// void operator=(const RawData &raw_data){
// strcpy(data, raw_data.data);
// }
};
};
template <typename... Ts> struct Variant {
template <typename... Ts> struct Variant {
Variant(const Variant &variant) {
// std::cout << " 赋值构造函数 " << std::endl;
type_id = variant.type_id;
......@@ -87,13 +87,13 @@ template <typename... Ts> struct Variant {
size_t TypeId() const { return type_id; }
private:
private:
static inline size_t invalid_type() { return typeid(void).hash_code(); }
typedef VariantHelper<Ts...> helper;
size_t type_id;
RawData<helper::size> data;
};
};
template <typename T> struct Vistor { typedef T type_t; };
template <typename T> struct Vistor { typedef T type_t; };
} // namespace paddle_mobile
......@@ -19,5 +19,5 @@ SOFTWARE.
#include "attribute.h"
namespace paddle_mobile {
namespace framework {}
namespace framework {}
} // namespace paddle_mobile
......@@ -22,13 +22,14 @@ SOFTWARE.
#include "framework.pb.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
class BlockDesc;
class BlockDesc;
class Attribute {
public:
static Attribute GetAttrValue(const proto::OpDesc::Attr &attr_desc) {
class Attribute {
public:
static Attribute
GetAttrValue(const proto::OpDesc::Attr &attr_desc) {
// std::cout << "begin get attr value" << std::endl;
Attribute attr;
switch (attr_desc.type()) {
......@@ -93,36 +94,38 @@ public:
}
Attribute() {}
template <typename T, typename... Args> Attribute &Set(Args &&... args) {
template <typename T, typename... Args>
Attribute &Set(Args &&... args) {
variant_.Set<T>(args...);
return *this;
}
template <typename T> T &Get() const { return variant_.Get<T>(); }
private:
Variant<int, float, std::string, std::vector<int>, std::vector<float>,
std::vector<std::string>, bool, std::vector<bool>, BlockDesc *,
int64_t>
private:
Variant<int, float, std::string, std::vector<int>,
std::vector<float>, std::vector<std::string>, bool,
std::vector<bool>, BlockDesc *, int64_t>
variant_;
};
};
using AttributeMap = std::unordered_map<std::string, Attribute>;
using AttributeMap = std::unordered_map<std::string, Attribute>;
class AttrReader {
public:
class AttrReader {
public:
explicit AttrReader(const AttributeMap &attrs) : attrs_(attrs) {}
template <typename T> inline T Get(const std::string &name) const {
// PADDLE_ENFORCE(attrs_.count(name) != 0, "%s should be in
// PADDLE_ENFORCE(attrs_.count(name) != 0, "%s should
// be in
// AttributeMap",
// name);
return ((Attribute)attrs_.at(name)).Get<T>();
}
private:
private:
const AttributeMap &attrs_;
};
};
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -19,32 +19,32 @@ SOFTWARE.
#include "block_desc.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
std::vector<std::shared_ptr<VarDesc>> BlockDesc::Vars() const {
std::vector<std::shared_ptr<VarDesc>> BlockDesc::Vars() const {
std::vector<std::shared_ptr<VarDesc>> res;
for (const auto &p : vars_) {
res.push_back(p.second);
}
return res;
}
}
std::vector<std::shared_ptr<OpDesc>> BlockDesc::Ops() const {
std::vector<std::shared_ptr<OpDesc>> BlockDesc::Ops() const {
std::vector<std::shared_ptr<OpDesc>> res;
for (const auto &op : ops_) {
res.push_back(op);
}
return res;
}
}
BlockDesc::BlockDesc(const proto::BlockDesc &desc) : desc_(desc) {
BlockDesc::BlockDesc(const proto::BlockDesc &desc) : desc_(desc) {
for (const proto::VarDesc &var_desc : desc_.vars()) {
vars_[var_desc.name()].reset(new VarDesc(var_desc));
}
for (const proto::OpDesc &op_desc : desc_.ops()) {
ops_.emplace_back(new framework::OpDesc(op_desc));
}
}
}
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -24,39 +24,43 @@ SOFTWARE.
#include "var_desc.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
class BlockDesc : PaddleMobileObject {
public:
class BlockDesc : PaddleMobileObject {
public:
BlockDesc(const proto::BlockDesc &desc);
const int &ID() const { return desc_.idx(); }
const int &Parent() const { return desc_.parent_idx(); }
bool operator==(const paddle_mobile::framework::BlockDesc &in_block) const {
return this->ID() == in_block.ID() && this->Parent() == in_block.Parent();
bool operator==(
const paddle_mobile::framework::BlockDesc &in_block) const {
return this->ID() == in_block.ID() &&
this->Parent() == in_block.Parent();
}
bool operator<(const paddle_mobile::framework::BlockDesc &in_block) const {
return this->ID() < in_block.ID() && this->Parent() < in_block.Parent();
bool operator<(
const paddle_mobile::framework::BlockDesc &in_block) const {
return this->ID() < in_block.ID() &&
this->Parent() < in_block.Parent();
}
std::vector<std::shared_ptr<VarDesc>> Vars() const;
std::vector<std::shared_ptr<OpDesc>> Ops() const;
private:
private:
proto::BlockDesc desc_;
std::vector<std::shared_ptr<OpDesc>> ops_;
std::unordered_map<std::string, std::shared_ptr<VarDesc>> vars_;
};
};
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
namespace std {
template <> struct hash<paddle_mobile::framework::BlockDesc> {
template <> struct hash<paddle_mobile::framework::BlockDesc> {
typedef paddle_mobile::framework::BlockDesc argument_type;
typedef std::size_t result_type;
result_type operator()(argument_type const &s) const noexcept {
......@@ -64,6 +68,6 @@ template <> struct hash<paddle_mobile::framework::BlockDesc> {
result_type const h2(std::hash<int>{}(s.ID()));
return h1 ^ (h2 << 1);
}
};
};
} // namespace std
......@@ -19,15 +19,15 @@ limitations under the License. */
#include <string>
namespace paddle_mobile {
namespace framework {
namespace framework {
enum class DataLayout {
enum class DataLayout {
kNHWC = 0,
kNCHW = 1,
kAnyLayout = 2,
};
};
inline DataLayout StringToDataLayout(const std::string &str) {
inline DataLayout StringToDataLayout(const std::string &str) {
std::string s(str);
for (size_t i = 0; i < s.size(); ++i) {
s[i] = toupper(s[i]);
......@@ -42,9 +42,9 @@ inline DataLayout StringToDataLayout(const std::string &str) {
} else {
// std::cout << "Unknown storage order string: %s", s;
}
}
}
inline std::string DataLayoutToString(const DataLayout &data_layout) {
inline std::string DataLayoutToString(const DataLayout &data_layout) {
switch (data_layout) {
case DataLayout::kNHWC:
return "NHWC";
......@@ -56,12 +56,13 @@ inline std::string DataLayoutToString(const DataLayout &data_layout) {
break;
// std::cout << "unknown DataLayou %d", data_layout;
}
}
}
inline std::ostream &operator<<(std::ostream &out, const DataLayout &l) {
inline std::ostream &operator<<(std::ostream &out,
const DataLayout &l) {
out << DataLayoutToString(l);
return out;
}
}
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -21,14 +21,14 @@ SOFTWARE.
#include "data_transform.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
static void PassTensorData(Tensor *from, Tensor *to) {
static void PassTensorData(Tensor *from, Tensor *to) {
to->ShareDataWith(*from);
*from = Tensor();
}
}
void DataTransform(const OpKernelType &expected_kernel_type,
void DataTransform(const OpKernelType &expected_kernel_type,
const OpKernelType &kernel_type_for_var,
const Tensor &input_tensor, Tensor *output_tensor) {
bool transformed = false;
......@@ -39,14 +39,17 @@ void DataTransform(const OpKernelType &expected_kernel_type,
// // do layout transform
// if (NeedTransformLayout(expected_kernel_type.data_layout_,
// kernel_type_for_var.data_layout_)) {
// TransDataLayout(kernel_type_for_var, expected_kernel_type, in, &out);
// TransDataLayout(kernel_type_for_var, expected_kernel_type, in,
// &out);
// transformed = true;
// PassTensorData(&out, &in);
// }
//
// // do data type transform
// if (expected_kernel_type.data_type_ != kernel_type_for_var.data_type_) {
// TransDataType(kernel_type_for_var, expected_kernel_type, in, &out);
// if (expected_kernel_type.data_type_ !=
// kernel_type_for_var.data_type_) {
// TransDataType(kernel_type_for_var, expected_kernel_type, in,
// &out);
// transformed = true;
// PassTensorData(&out, &in);
// }
......@@ -59,13 +62,14 @@ void DataTransform(const OpKernelType &expected_kernel_type,
// PassTensorData(&out, &in);
// }
//
// PADDLE_ENFORCE(transformed, "No transform is applied, please check!");
// PADDLE_ENFORCE(transformed, "No transform is applied, please
// check!");
// get output data
output_tensor->ShareDataWith(in);
}
}
void CopyVariableWithTensor(const Variable &in_var, const Tensor &tensor,
Variable &out_var) {
void CopyVariableWithTensor(const Variable &in_var,
const Tensor &tensor, Variable &out_var) {
// if (in_var.IsType<LoDTensor>()) {
// auto& in_lod_tensor = in_var.Get<LoDTensor>();
// auto* tran_lod_tensor = out_var.GetMutable<LoDTensor>();
......@@ -74,14 +78,15 @@ void CopyVariableWithTensor(const Variable &in_var, const Tensor &tensor,
// tran_lod_tensor->ShareDataWith(tensor);
// } else if (in_var.IsType<SelectedRows>()) {
// auto& in_selected_rows = in_var.Get<SelectedRows>();
// auto* trans_selected_rows = out_var.GetMutable<SelectedRows>();
// auto* trans_selected_rows =
// out_var.GetMutable<SelectedRows>();
// trans_selected_rows->set_height(in_selected_rows.height());
// trans_selected_rows->set_rows(in_selected_rows.rows());
// trans_selected_rows->mutable_value()->ShareDataWith(tensor);
// } else {
// PADDLE_THROW("unknown var type");
// }
}
}
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -28,14 +28,14 @@ SOFTWARE.
#include "variable.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
void DataTransform(const OpKernelType &expected_kernel_type,
void DataTransform(const OpKernelType &expected_kernel_type,
const OpKernelType &kernel_type_for_var,
const Tensor &input_tensor, Tensor *out);
void CopyVariableWithTensor(const Variable &in_var, const Tensor &tensor,
Variable &out_var);
void CopyVariableWithTensor(const Variable &in_var,
const Tensor &tensor, Variable &out_var);
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -21,23 +21,23 @@ SOFTWARE.
#include "framework.pb.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
// inline proto::VarType::Type ToDataType(std::type_index type) {
// using namespace paddle_mobile::framework::proto;
// if (typeid(float).hash_code() == type.hash_code()) {
// return proto::VarType::FP32;
// } else if (typeid(double).hash_code() == type.hash_code()) {
// return proto::VarType::FP64;
// } else if (typeid(int).hash_code() == type.hash_code()) {
// return proto::VarType::INT32;
// } else if (typeid(int64_t).hash_code() == type.hash_code()) {
// return proto::VarType::INT64;
// } else if (typeid(bool).hash_code() == type.hash_code()) {
// return proto::VarType::BOOL;
// } else {
//// PADDLE_THROW("Not supported");
// }
// }
}
// inline proto::VarType::Type ToDataType(std::type_index type) {
// using namespace paddle_mobile::framework::proto;
// if (typeid(float).hash_code() == type.hash_code()) {
// return proto::VarType::FP32;
// } else if (typeid(double).hash_code() == type.hash_code()) {
// return proto::VarType::FP64;
// } else if (typeid(int).hash_code() == type.hash_code()) {
// return proto::VarType::INT32;
// } else if (typeid(int64_t).hash_code() == type.hash_code()) {
// return proto::VarType::INT64;
// } else if (typeid(bool).hash_code() == type.hash_code()) {
// return proto::VarType::BOOL;
// } else {
//// PADDLE_THROW("Not supported");
// }
// }
}
} // namespace paddle_mobile
......@@ -15,17 +15,17 @@ limitations under the License. */
#include "ddim.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
/// @cond HIDDEN
/// @cond HIDDEN
template <int i> Dim<i> make_dim(const int64_t *d) {
template <int i> Dim<i> make_dim(const int64_t *d) {
return Dim<i>(*d, make_dim<i - 1>(d + 1));
}
}
template <> Dim<0> make_dim<0>(const int64_t *d) { return Dim<0>(*d); }
template <> Dim<0> make_dim<0>(const int64_t *d) { return Dim<0>(*d); }
void make_ddim(DDim &ddim, const int64_t *dims, int n) {
void make_ddim(DDim &ddim, const int64_t *dims, int n) {
switch (n) {
case 0:
ddim = make_dim<0>(dims);
......@@ -58,70 +58,74 @@ void make_ddim(DDim &ddim, const int64_t *dims, int n) {
ddim = make_dim<9>(dims);
break;
default:
// std::cout << "Dynamic dimensions must have between [1, 9]
// std::cout << "Dynamic dimensions must have between [1,
// 9]
// dimensions.";
break;
}
}
}
/// @endcond
/// @endcond
DDim make_ddim(std::initializer_list<int64_t> dims) {
DDim make_ddim(std::initializer_list<int64_t> dims) {
DDim result(make_dim(0));
make_ddim(result, dims.begin(), dims.size());
return result;
}
}
DDim make_ddim(const std::vector<int64_t> &dims) {
DDim make_ddim(const std::vector<int64_t> &dims) {
DDim result(make_dim(0));
make_ddim(result, &dims[0], dims.size());
return result;
}
}
DDim make_ddim(const std::vector<int> &dims) {
DDim make_ddim(const std::vector<int> &dims) {
std::vector<int64_t> res(dims.size());
std::transform(dims.begin(), dims.end(), res.begin(),
[](int d) { return static_cast<int64_t>(d); });
return make_ddim(res);
}
}
/// @cond HIDDEN
// XXX For some reason, putting this in an anonymous namespace causes errors
struct DynamicMutableIndexer : Vistor<int64_t &> {
public:
/// @cond HIDDEN
// XXX For some reason, putting this in an anonymous namespace causes
// errors
struct DynamicMutableIndexer : Vistor<int64_t &> {
public:
explicit DynamicMutableIndexer(int idx) : idx_(idx) {}
template <int D> int64_t &operator()(Dim<D> &dim) const { return dim[idx_]; }
template <int D> int64_t &operator()(Dim<D> &dim) const {
return dim[idx_];
}
private:
private:
int idx_;
};
};
struct DynamicConstIndexer : public Vistor<int64_t> {
public:
struct DynamicConstIndexer : public Vistor<int64_t> {
public:
explicit DynamicConstIndexer(int idx) : idx_(idx) {}
template <int D> int64_t operator()(const Dim<D> &dim) const {
return dim[idx_];
}
private:
private:
int idx_;
};
};
/// @endcond
/// @endcond
int64_t &DDim::operator[](int idx) {
int64_t &DDim::operator[](int idx) {
return DDim::ApplyVistor(DynamicMutableIndexer(idx), *this);
}
}
int64_t DDim::operator[](int idx) const {
int64_t DDim::operator[](int idx) const {
return DDim::ApplyVistor(DynamicConstIndexer(idx), *this);
}
}
int DDim::size() const { return arity(*this); }
int DDim::size() const { return arity(*this); }
bool DDim::operator==(DDim d) const {
bool DDim::operator==(DDim d) const {
// if (var.which() != d.getVar().which()) {
// return false;
// } else {
......@@ -136,11 +140,11 @@ bool DDim::operator==(DDim d) const {
return true;
// }
}
}
bool DDim::operator!=(DDim d) const { return !(*this == d); }
bool DDim::operator!=(DDim d) const { return !(*this == d); }
DDim DDim::operator+(DDim d) const {
DDim DDim::operator+(DDim d) const {
std::vector<int64_t> v1 = vectorize(*this);
std::vector<int64_t> v2 = vectorize(d);
......@@ -153,9 +157,9 @@ DDim DDim::operator+(DDim d) const {
}
return make_ddim(v3);
}
}
DDim DDim::operator*(DDim d) const {
DDim DDim::operator*(DDim d) const {
std::vector<int64_t> v1 = vectorize(*this);
std::vector<int64_t> v2 = vectorize(d);
......@@ -168,14 +172,14 @@ DDim DDim::operator*(DDim d) const {
}
return make_ddim(v3);
}
}
int64_t get(const DDim &ddim, int idx) { return ddim[idx]; }
int64_t get(const DDim &ddim, int idx) { return ddim[idx]; }
void set(DDim &ddim, int idx, int value) { ddim[idx] = value; }
void set(DDim &ddim, int idx, int value) { ddim[idx] = value; }
/// @cond HIDDEN
struct VectorizeVisitor : Vistor<void> {
/// @cond HIDDEN
struct VectorizeVisitor : Vistor<void> {
std::vector<int64_t> &vector;
explicit VectorizeVisitor(std::vector<int64_t> &v) : vector(v) {}
......@@ -186,36 +190,36 @@ struct VectorizeVisitor : Vistor<void> {
}
void operator()(const Dim<0> &t) {}
};
/// @endcond
};
/// @endcond
std::vector<int64_t> vectorize(const DDim &ddim) {
std::vector<int64_t> vectorize(const DDim &ddim) {
std::vector<int64_t> result;
VectorizeVisitor visitor(result);
DDim::ApplyVistor(visitor, ddim);
return result;
}
}
// NOTE: framework::vectorize converts to type int64_t
// which does not fit cudnn inputs.
std::vector<int> vectorize2int(const DDim &ddim) {
// NOTE: framework::vectorize converts to type int64_t
// which does not fit cudnn inputs.
std::vector<int> vectorize2int(const DDim &ddim) {
std::vector<int64_t> temp = vectorize(ddim);
std::vector<int> result(temp.begin(), temp.end());
return result;
}
}
struct ProductVisitor : Vistor<int64_t> {
struct ProductVisitor : Vistor<int64_t> {
template <int D> int64_t operator()(const Dim<D> &dim) {
return product(dim);
}
};
};
int64_t product(const DDim &ddim) {
int64_t product(const DDim &ddim) {
ProductVisitor visitor;
return DDim::ApplyVistor(visitor, ddim);
}
}
struct SliceVectorizeVisitor : Vistor<void> {
struct SliceVectorizeVisitor : Vistor<void> {
std::vector<int64_t> &vector;
int begin;
int end;
......@@ -223,10 +227,12 @@ struct SliceVectorizeVisitor : Vistor<void> {
SliceVectorizeVisitor(std::vector<int64_t> &v, int b, int e)
: vector(v), begin(b), end(e) {
// PADDLE_ENFORCE(begin < end,
// "Begin index must be less than end index in ddim
// "Begin index must be less than end index in
// ddim
// slice.");
// PADDLE_ENFORCE(begin >= 0,
// "Begin index can't be less than zero in ddim slice.");
// "Begin index can't be less than zero in
// ddim slice.");
}
template <int S> void operator()(const Dim<S> &dim) {
......@@ -242,11 +248,12 @@ struct SliceVectorizeVisitor : Vistor<void> {
}
void operator()(const Dim<0> &dim) {
// PADDLE_ENFORCE(end == 0, "End index in ddim slice is out of bound.");
// PADDLE_ENFORCE(end == 0, "End index in ddim slice is out
// of bound.");
}
};
};
DDim slice_ddim(const DDim &ddim, int begin, int end) {
DDim slice_ddim(const DDim &ddim, int begin, int end) {
std::vector<int64_t> vec;
vec.reserve(end - begin);
SliceVectorizeVisitor visitor(vec, begin, end);
......@@ -254,72 +261,74 @@ DDim slice_ddim(const DDim &ddim, int begin, int end) {
DDim::ApplyVistor(visitor, ddim);
// visitor(ddim.var.Get<Dim<4>>());
return make_ddim(vec);
}
}
/// \cond HIDDEN
/// \cond HIDDEN
struct ArityVisitor : Vistor<int> {
struct ArityVisitor : Vistor<int> {
template <int D> int operator()(Dim<D>) const { return D; }
};
};
/// \endcond
/// \endcond
int arity(const DDim &d) {
int arity(const DDim &d) {
ArityVisitor arityVisitor = ArityVisitor();
return DDim::ApplyVistor(arityVisitor, d);
// return arityVisitor(d.var.Get<Dim<4>>());
// return boost::apply_visitor(ArityVisitor(), d); }
}
/// \cond HIDDEN
}
/// \cond HIDDEN
/// \endcond
/// \endcond
struct OSVistor : Vistor<std::ostream &> {
struct OSVistor : Vistor<std::ostream &> {
OSVistor(std::ostream &os) : os_(os) {}
template <int D> std::ostream &operator()(Dim<D> dim) const {
return os_ << dim;
}
private:
private:
std::ostream &os_;
};
};
std::ostream &operator<<(std::ostream &os, const DDim &ddim) {
std::ostream &operator<<(std::ostream &os, const DDim &ddim) {
auto vistor = OSVistor(os);
DDim::ApplyVistor(vistor, ddim);
return os;
}
}
DDim::DDim(std::initializer_list<int64_t> init_list) {
DDim::DDim(std::initializer_list<int64_t> init_list) {
*this = make_ddim(init_list);
}
}
DDim flatten_to_2d(const DDim &src, int num_col_dims) {
DDim flatten_to_2d(const DDim &src, int num_col_dims) {
int rank = src.size();
return make_ddim({product(slice_ddim(src, 0, num_col_dims)),
product(slice_ddim(src, num_col_dims, rank))});
}
}
DDim flatten_to_1d(const DDim &src) { return make_ddim({product(src)}); }
DDim flatten_to_1d(const DDim &src) {
return make_ddim({product(src)});
}
DDim stride(const DDim &ddim) {
DDim stride(const DDim &ddim) {
std::vector<int64_t> strides(ddim.size());
strides[ddim.size() - 1] = 1;
for (int i = ddim.size() - 2; i >= 0; --i) {
strides[i] = strides[i + 1] * ddim[i + 1];
}
return framework::make_ddim(strides);
}
}
DDim stride_numel(const framework::DDim &ddim) {
DDim stride_numel(const framework::DDim &ddim) {
std::vector<int64_t> strides(ddim.size());
strides[ddim.size() - 1] = ddim[ddim.size() - 1];
for (int i = ddim.size() - 2; i >= 0; --i) {
strides[i] = strides[i + 1] * ddim[i];
}
return framework::make_ddim(strides);
}
}
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -22,21 +22,22 @@ limitations under the License. */
#include <vector>
namespace paddle_mobile {
namespace framework {
namespace framework {
/**
/**
* \brief A dynamically sized dimension.
*
* The number of dimensions must be between [1, 9].
*/
struct DDim {
typedef Variant<Dim<0>, Dim<1>, Dim<2>, Dim<3>, Dim<4>, Dim<5>, Dim<6>,
Dim<7>, Dim<8>, Dim<9>>
struct DDim {
typedef Variant<Dim<0>, Dim<1>, Dim<2>, Dim<3>, Dim<4>, Dim<5>,
Dim<6>, Dim<7>, Dim<8>, Dim<9>>
DDimVar;
DDimVar var;
template <typename Vistor>
static typename Vistor::type_t ApplyVistor(Vistor vistor, const DDim &d) {
static typename Vistor::type_t ApplyVistor(Vistor vistor,
const DDim &d) {
if (d.var.TypeId() == typeid(Dim<0>).hash_code()) {
return vistor(d.var.Get<Dim<0>>());
} else if (d.var.TypeId() == typeid(Dim<1>).hash_code()) {
......@@ -66,7 +67,9 @@ struct DDim {
DDim() { var.Set<Dim<1>>(Dim<1>()); }
template <int D> explicit DDim(const Dim<D> &in) { var.Set<Dim<D>>(in); }
template <int D> explicit DDim(const Dim<D> &in) {
var.Set<Dim<D>>(in);
}
/*implicit*/ DDim(std::initializer_list<int64_t> init_list);
......@@ -85,7 +88,8 @@ struct DDim {
// }
//
// template <typename Visitor>
// typename Visitor::result_type apply_visitor(Visitor& visitor) const {
// typename Visitor::result_type apply_visitor(Visitor& visitor)
// const {
// return var.apply_visitor(visitor);
// }
......@@ -100,62 +104,63 @@ struct DDim {
DDim operator*(DDim d) const;
int size() const;
};
};
/**
/**
* \brief Make a DDim from std::vector<int64_t>
*
* \param dims An vector of ints. Must be sized between [1, 9]
*/
DDim make_ddim(const std::vector<int64_t> &dims);
DDim make_ddim(const std::vector<int64_t> &dims);
DDim make_ddim(const std::vector<int> &dims);
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<int64_t> dims);
DDim make_ddim(std::initializer_list<int64_t> dims);
int64_t get(const DDim &dim, int idx);
int64_t get(const DDim &dim, int idx);
void set(DDim &dim, int idx, int val);
void set(DDim &dim, int idx, int val);
std::vector<int64_t> vectorize(const DDim &ddim);
std::vector<int64_t> vectorize(const DDim &ddim);
std::vector<int> vectorize2int(const DDim &ddim);
std::vector<int> vectorize2int(const DDim &ddim);
int64_t product(const DDim &ddim);
int64_t product(const DDim &ddim);
/**
/**
* \brief Slice a ddim
*
* Slice dim with [begin, end).
* e.g. DDim d = make_ddim({1,2,3,4,5});
* slice_ddim(d, 1, 3); ====> {2,3}
*/
DDim slice_ddim(const DDim &dim, int begin, int end);
DDim slice_ddim(const DDim &dim, int begin, int end);
/**
/**
* \brief What is the length of this dimension?
*
* \param Dynamic dimension to inspect
*/
int arity(const DDim &ddim);
int arity(const DDim &ddim);
std::ostream &operator<<(std::ostream &, const DDim &);
std::ostream &operator<<(std::ostream &, const DDim &);
// Reshape a tensor to a matrix. The matrix's first dimension(column length)
// will be the product of tensor's first `num_col_dims` dimensions.
DDim flatten_to_2d(const DDim &src, int num_col_dims);
// Reshape a tensor to a matrix. The matrix's first dimension(column
// length)
// will be the product of tensor's first `num_col_dims` dimensions.
DDim flatten_to_2d(const DDim &src, int num_col_dims);
DDim flatten_to_1d(const DDim &src);
DDim flatten_to_1d(const DDim &src);
DDim stride(const DDim &ddim);
DDim stride(const DDim &ddim);
DDim stride_numel(const DDim &ddim);
} // namespace framework
DDim stride_numel(const DDim &ddim);
} // namespace framework
} // namespace paddle_mobile
......@@ -21,25 +21,29 @@
#include "platform/hostdevice.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
// Statically sized, statically indexed dimension
template <int i> struct Dim {
// Statically sized, statically indexed dimension
template <int i> struct Dim {
static constexpr int dimensions = i;
template <typename... Args>
HOSTDEVICE Dim(int64_t _head, Args... _tail) : head(_head), tail(_tail...) {
static_assert(sizeof...(_tail) == i - 1,
HOSTDEVICE Dim(int64_t _head, Args... _tail)
: head(_head), tail(_tail...) {
static_assert(
sizeof...(_tail) == i - 1,
"Dim initialized with the wrong number of parameters");
}
HOSTDEVICE
Dim(int64_t _head, const Dim<i - 1> &_tail) : head(_head), tail(_tail) {}
Dim(int64_t _head, const Dim<i - 1> &_tail)
: head(_head), tail(_tail) {}
HOSTDEVICE
Dim() : head(0), tail() {}
/** Construct a Dim from a linear index and size. Uses Fortran order
/** Construct a Dim from a linear index and size. Uses Fortran
* order
* indexing. */
HOSTDEVICE
Dim(int64_t idx, const Dim<i> &size)
......@@ -66,10 +70,10 @@ template <int i> struct Dim {
int64_t head;
Dim<i - 1> tail;
};
};
// Base case specialization
template <> struct Dim<0> {
// Base case specialization
template <> struct Dim<0> {
static constexpr int dimensions = 0;
HOSTDEVICE
......@@ -99,36 +103,41 @@ template <> struct Dim<0> {
int64_t &operator[](int idx);
HOSTDEVICE
int64_t operator[](int idx) const;
};
};
namespace {
namespace {
// Helper for accessing Dim classes
template <int i> struct DimGetter {
// Helper for accessing Dim classes
template <int i> struct DimGetter {
// Return a copy if Dim is const
template <typename D> HOSTDEVICE static int64_t impl(const D &d) {
template <typename D>
HOSTDEVICE static int64_t impl(const D &d) {
return DimGetter<i - 1>::impl(d.tail);
}
// Return a reference if Dim is mutable
template <typename D> HOSTDEVICE static int64_t &impl(D &d) {
return DimGetter<i - 1>::impl(d.tail);
}
};
};
// Eureka! We found the element!
template <> struct DimGetter<0> {
// Eureka! We found the element!
template <> struct DimGetter<0> {
// Return a copy if Dim is const
template <typename D> HOSTDEVICE static int64_t impl(const D &d) {
template <typename D>
HOSTDEVICE static int64_t impl(const D &d) {
return d.head;
}
// Return a reference if Dim is mutable
template <typename D> HOSTDEVICE static int64_t &impl(D &d) { return d.head; }
};
template <typename D> HOSTDEVICE static int64_t &impl(D &d) {
return d.head;
}
};
template <int D> HOSTDEVICE int64_t &indexer(Dim<D> &dim, int idx) {
template <int D> HOSTDEVICE int64_t &indexer(Dim<D> &dim, int idx) {
#ifndef __CUDA_ARCH__
if (idx < 0) {
throw std::invalid_argument("Tried to access a negative dimension");
throw std::invalid_argument(
"Tried to access a negative dimension");
}
#else
PADDLE_ASSERT(idx >= 0);
......@@ -137,9 +146,9 @@ template <int D> HOSTDEVICE int64_t &indexer(Dim<D> &dim, int idx) {
return dim.head;
}
return indexer(dim.tail, idx - 1);
}
}
template <> HOSTDEVICE int64_t &indexer<0>(Dim<0> &dim, int idx) {
template <> HOSTDEVICE int64_t &indexer<0>(Dim<0> &dim, int idx) {
#ifndef __CUDA_ARCH__
throw std::invalid_argument("Invalid index");
#else
......@@ -153,12 +162,14 @@ template <> HOSTDEVICE int64_t &indexer<0>(Dim<0> &dim, int idx) {
#endif
return head;
#endif
}
}
template <int D> HOSTDEVICE int64_t indexer(const Dim<D> &dim, int idx) {
template <int D>
HOSTDEVICE int64_t indexer(const Dim<D> &dim, int idx) {
#ifndef __CUDA_ARCH__
if (idx < 0) {
throw std::invalid_argument("Tried to access a negative dimension");
throw std::invalid_argument(
"Tried to access a negative dimension");
}
#else
PADDLE_ASSERT(idx >= 0);
......@@ -167,9 +178,10 @@ template <int D> HOSTDEVICE int64_t indexer(const Dim<D> &dim, int idx) {
return dim.head;
}
return indexer(dim.tail, idx - 1);
}
}
template <> HOSTDEVICE int64_t indexer<0>(const Dim<0> &dim, int idx) {
template <>
HOSTDEVICE int64_t indexer<0>(const Dim<0> &dim, int idx) {
#ifndef __CUDA_ARCH__
throw std::invalid_argument("Invalid index");
#else
......@@ -183,146 +195,152 @@ template <> HOSTDEVICE int64_t indexer<0>(const Dim<0> &dim, int idx) {
#endif
return head;
#endif
}
}
} // namespace
// Static access to constant Dim
template <int i, int l> HOSTDEVICE int64_t get(const Dim<l> &d) {
} // namespace
// Static access to constant Dim
template <int i, int l> HOSTDEVICE int64_t get(const Dim<l> &d) {
return DimGetter<i>::impl(d);
}
}
// Static access to mutable Dim
template <int i, int l> HOSTDEVICE int64_t &get(Dim<l> &d) {
// Static access to mutable Dim
template <int i, int l> HOSTDEVICE int64_t &get(Dim<l> &d) {
return DimGetter<i>::impl(d);
}
}
// Dynamic access to constant Dim
template <int l> HOSTDEVICE int64_t Dim<l>::operator[](int i) const {
// Dynamic access to constant Dim
template <int l> HOSTDEVICE int64_t Dim<l>::operator[](int i) const {
// std::cout << "l: " << l << std::endl;
return indexer(*this, i);
}
}
// Dynamic access to mutable Dim
template <int l> HOSTDEVICE int64_t &Dim<l>::operator[](int i) {
// Dynamic access to mutable Dim
template <int l> HOSTDEVICE int64_t &Dim<l>::operator[](int i) {
return indexer(*this, i);
}
}
// Dynamic access to constant Dim
inline HOSTDEVICE int64_t Dim<0>::operator[](int i) const {
// Dynamic access to constant Dim
inline HOSTDEVICE int64_t Dim<0>::operator[](int i) const {
return indexer(*this, i);
}
}
// Dynamic access to mutable Dim
inline HOSTDEVICE int64_t &Dim<0>::operator[](int i) {
// Dynamic access to mutable Dim
inline HOSTDEVICE int64_t &Dim<0>::operator[](int i) {
return indexer(*this, i);
}
}
// Dynamic access to constant Dim
// without std::enable_if will try to instantiate this on get<0>(d)
template <int l>
HOSTDEVICE typename std::enable_if<(l > 0), int64_t>::type get(const Dim<l> &d,
int i) {
// Dynamic access to constant Dim
// without std::enable_if will try to instantiate this on get<0>(d)
template <int l>
HOSTDEVICE typename std::enable_if<(l > 0), int64_t>::type
get(const Dim<l> &d, int i) {
return d[i];
}
}
// Dynamic access to mutable Dim
template <int l>
HOSTDEVICE typename std::enable_if<(l > 0), int64_t &>::type get(Dim<l> &d,
int i) {
// Dynamic access to mutable Dim
template <int l>
HOSTDEVICE typename std::enable_if<(l > 0), int64_t &>::type
get(Dim<l> &d, int i) {
return d[i];
}
}
// Dot product of two dims
template <int i>
HOSTDEVICE int64_t linearize(const Dim<i> &a, const Dim<i> &b) {
// Dot product of two dims
template <int i>
HOSTDEVICE int64_t linearize(const Dim<i> &a, const Dim<i> &b) {
return a.head * b.head + linearize(a.tail, b.tail);
}
}
// Base case dot product of two Dims
// Notice it is inline because it is no longer a template
template <>
HOSTDEVICE inline int64_t linearize(const Dim<0> &a, const Dim<0> &b) {
// Base case dot product of two Dims
// Notice it is inline because it is no longer a template
template <>
HOSTDEVICE inline int64_t linearize(const Dim<0> &a, const Dim<0> &b) {
return 0;
}
}
// Product of a Dim
template <int i> HOSTDEVICE int64_t product(const Dim<i> &a, int prod = 1) {
// Product of a Dim
template <int i>
HOSTDEVICE int64_t product(const Dim<i> &a, int prod = 1) {
return prod * a.head * product(a.tail);
}
}
// Base case product of a Dim
// Notice it is inline because it is no longer a template
template <> HOSTDEVICE inline int64_t product(const Dim<0> &a, int prod) {
// Base case product of a Dim
// Notice it is inline because it is no longer a template
template <>
HOSTDEVICE inline int64_t product(const Dim<0> &a, int prod) {
return prod;
}
}
// Is 0 <= idx_i < size_i for all i?
template <int i>
HOSTDEVICE bool contained(const Dim<i> &idx, const Dim<i> &size) {
// Is 0 <= idx_i < size_i for all i?
template <int i>
HOSTDEVICE bool contained(const Dim<i> &idx, const Dim<i> &size) {
return ((0 <= idx.head) && (idx.head < size.head) &&
contained(idx.tail, size.tail));
}
}
// Base case of is 0 <= idx_i < size_i ?
// Notice it is inline because it is no longer a template
template <>
HOSTDEVICE inline bool contained(const Dim<0> &idx, const Dim<0> &size) {
// Base case of is 0 <= idx_i < size_i ?
// Notice it is inline because it is no longer a template
template <>
HOSTDEVICE inline bool contained(const Dim<0> &idx,
const Dim<0> &size) {
return true;
}
}
/**
/**
* \brief Compute exclusive prefix-multiply of a Dim.
*/
template <int i>
HOSTDEVICE Dim<i> ex_prefix_mul(const Dim<i> &src, int mul = 1) {
template <int i>
HOSTDEVICE Dim<i> ex_prefix_mul(const Dim<i> &src, int mul = 1) {
return Dim<i>(mul, ex_prefix_mul(src.tail, mul * src.head));
}
}
///\cond HIDDEN
// Base case of ex_prefix_mul
// Notice it is inline because it is no longer a template
template <> HOSTDEVICE inline Dim<0> ex_prefix_mul(const Dim<0> &src, int mul) {
///\cond HIDDEN
// Base case of ex_prefix_mul
// Notice it is inline because it is no longer a template
template <>
HOSTDEVICE inline Dim<0> ex_prefix_mul(const Dim<0> &src, int mul) {
return Dim<0>();
}
///\endcond
}
///\endcond
/**
/**
* Add two dimensions together
*/
template <int i> HOSTDEVICE Dim<i> dim_plus(const Dim<i> &a, const Dim<i> &b) {
template <int i>
HOSTDEVICE Dim<i> dim_plus(const Dim<i> &a, const Dim<i> &b) {
return Dim<i>(a.head + b.head, dim_plus(a.tail, b.tail));
}
}
// Base case
template <>
HOSTDEVICE inline Dim<0> dim_plus(const Dim<0> &a, const Dim<0> &b) {
// Base case
template <>
HOSTDEVICE inline Dim<0> dim_plus(const Dim<0> &a, const Dim<0> &b) {
return Dim<0>();
}
}
template <int i>
HOSTDEVICE Dim<i> operator+(const Dim<i> &lhs, const Dim<i> &rhs) {
template <int i>
HOSTDEVICE Dim<i> operator+(const Dim<i> &lhs, const Dim<i> &rhs) {
return dim_plus(lhs, rhs);
}
}
/**
/**
* Multiply two dimensions together
*/
template <int i> HOSTDEVICE Dim<i> dim_mult(const Dim<i> &a, const Dim<i> &b) {
template <int i>
HOSTDEVICE Dim<i> dim_mult(const Dim<i> &a, const Dim<i> &b) {
return Dim<i>(a.head * b.head, dim_mult(a.tail, b.tail));
}
}
// Base case
template <>
HOSTDEVICE inline Dim<0> dim_mult(const Dim<0> &a, const Dim<0> &b) {
// Base case
template <>
HOSTDEVICE inline Dim<0> dim_mult(const Dim<0> &a, const Dim<0> &b) {
return Dim<0>();
}
}
template <int i>
HOSTDEVICE Dim<i> operator*(const Dim<i> &lhs, const Dim<i> &rhs) {
template <int i>
HOSTDEVICE Dim<i> operator*(const Dim<i> &lhs, const Dim<i> &rhs) {
return dim_mult(lhs, rhs);
}
}
/**
/**
* \brief Normalize strides to ensure any dimension with extent 1
* has stride 0.
*
......@@ -332,66 +350,70 @@ HOSTDEVICE Dim<i> operator*(const Dim<i> &lhs, const Dim<i> &rhs) {
*
*/
template <int i>
HOSTDEVICE Dim<i> normalize_strides(const Dim<i> &size, const Dim<i> &stride) {
template <int i>
HOSTDEVICE Dim<i> normalize_strides(const Dim<i> &size,
const Dim<i> &stride) {
int norm_stride = size.head == 1 ? 0 : stride.head;
return Dim<i>(norm_stride, normalize_strides(size.tail, stride.tail));
}
return Dim<i>(norm_stride,
normalize_strides(size.tail, stride.tail));
}
///\cond HIDDEN
///\cond HIDDEN
template <>
HOSTDEVICE inline Dim<0> normalize_strides(const Dim<0> &size,
template <>
HOSTDEVICE inline Dim<0> normalize_strides(const Dim<0> &size,
const Dim<0> &stride) {
return Dim<0>();
}
}
///\endcond
///\endcond
/**
/**
* Helper function to create a Dim
*
* \param idxes The type of Dim constructed depends on the number of params
* \param idxes The type of Dim constructed depends on the number of
* params
*
*/
template <typename... Args>
HOSTDEVICE Dim<sizeof...(Args)> make_dim(Args... idxes) {
template <typename... Args>
HOSTDEVICE Dim<sizeof...(Args)> make_dim(Args... idxes) {
return Dim<sizeof...(Args)>(idxes...);
}
}
// Allows us to output a Dim
// XXX For some reason, overloading fails to resolve this correctly
template <int i>
typename std::enable_if<(i > 1), std::ostream &>::type
operator<<(std::ostream &os, const Dim<i> &d) {
// Allows us to output a Dim
// XXX For some reason, overloading fails to resolve this correctly
template <int i>
typename std::enable_if<(i > 1), std::ostream &>::type
operator<<(std::ostream &os, const Dim<i> &d) {
os << d.head << ", " << d.tail;
return os;
}
}
// Base case that allows us to output a Dim
// XXX I wish this could be an overload instead of a template
template <int i>
typename std::enable_if<(i == 1), std::ostream &>::type
operator<<(std::ostream &os, const Dim<i> &d) {
// Base case that allows us to output a Dim
// XXX I wish this could be an overload instead of a template
template <int i>
typename std::enable_if<(i == 1), std::ostream &>::type
operator<<(std::ostream &os, const Dim<i> &d) {
os << d.head;
return os;
}
}
inline std::ostream &operator<<(std::ostream &os, const Dim<0> &d) {
inline std::ostream &operator<<(std::ostream &os, const Dim<0> &d) {
return os;
}
}
template <int i> HOST std::string Dim<i>::to_string() const {
template <int i> HOST std::string Dim<i>::to_string() const {
std::stringstream stream;
stream << *this;
return stream.str();
}
}
template <int D>
HOSTDEVICE Dim<D> linear_to_dimension(int linear_index, Dim<D> extents) {
template <int D>
HOSTDEVICE Dim<D> linear_to_dimension(int linear_index,
Dim<D> extents) {
Dim<D> result;
for (int i = 0; i < D - 1; ++i) {
......@@ -402,7 +424,7 @@ HOSTDEVICE Dim<D> linear_to_dimension(int linear_index, Dim<D> extents) {
result[D - 1] = linear_index;
return result;
}
}
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -23,10 +23,10 @@ SOFTWARE.
#include "variable.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
template <typename Dtype>
Executor<Dtype>::Executor(const Program<Dtype> p) : program_(p) {
template <typename Dtype>
Executor<Dtype>::Executor(const Program<Dtype> p) : program_(p) {
if (use_optimize_) {
to_predict_program_ = program_.optimizeProgram;
} else {
......@@ -42,34 +42,41 @@ Executor<Dtype>::Executor(const Program<Dtype> p) : program_(p) {
// std::cout << " ops " << ops.size() << std::endl;
for (int j = 0; j < ops.size(); ++j) {
std::shared_ptr<OpDesc> op = ops[j];
// std::cout << " input 0 " << op->Input("Input")[0] << std::endl;
if (op->Type() == "conv2d" && op->Input("Input")[0] == "pixel") {
// std::cout << " conv2d attr size: " << op->GetAttrMap().size()
// std::cout << " input 0 " << op->Input("Input")[0]
// << std::endl;
// std::cout << " input size: " << op->GetInputs().size() <<
if (op->Type() == "conv2d" &&
op->Input("Input")[0] == "pixel") {
// std::cout << " conv2d attr size: " <<
// op->GetAttrMap().size()
// << std::endl;
// std::cout << " input size: " <<
// op->GetInputs().size() <<
// std::endl;
// std::cout << " output size: " << op->GetOutputs().size() <<
// std::cout << " output size: " <<
// op->GetOutputs().size() <<
// std::endl;
Attribute strides_attr = op->GetAttrMap().at("strides");
std::vector<int> stride = strides_attr.Get<std::vector<int>>();
std::vector<int> stride =
strides_attr.Get<std::vector<int>>();
for (int k = 0; k < stride.size(); ++k) {
// std::cout << " stride " << stride[k] << std::endl;
// std::cout << " stride " << stride[k] <<
// std::endl;
}
std::shared_ptr<operators::ConvOp<Dtype, float>> conv =
std::make_shared<operators::ConvOp<Dtype, float>>(
op->Type(), op->GetInputs(), op->GetOutputs(), op->GetAttrMap(),
program_.scope);
op->Type(), op->GetInputs(), op->GetOutputs(),
op->GetAttrMap(), program_.scope);
ops_of_block_[*block_desc.get()].push_back(conv);
}
}
}
}
}
template <typename Dtype>
std::shared_ptr<Tensor> Executor<Dtype>::predict(Tensor &t) {
template <typename Dtype>
std::shared_ptr<Tensor> Executor<Dtype>::predict(Tensor &t) {
// feed
auto scope = program_.scope;
Variable *g_feed_value = scope->Var("pixel");
......@@ -80,27 +87,29 @@ std::shared_ptr<Tensor> Executor<Dtype>::predict(Tensor &t) {
Tensor *output_tensor = con_output->GetMutable<Tensor>();
output_tensor->mutable_data<float>({1, 16, 32, 32});
// std::cout << typeid(output_tensor).name() << std::endl;
// std::cout << "output_tensor dims: " << output_tensor->dims() << std::endl;
// std::cout << "output_tensor dims: " << output_tensor->dims() <<
// std::endl;
std::shared_ptr<Tensor> out_tensor = std::make_shared<LoDTensor>();
out_tensor.reset(output_tensor);
predict(t, 0);
return out_tensor;
}
}
template <typename Dtype>
void Executor<Dtype>::predict(const Tensor &t, int block_id) {
template <typename Dtype>
void Executor<Dtype>::predict(const Tensor &t, int block_id) {
std::shared_ptr<BlockDesc> to_predict_block =
to_predict_program_->Block(block_id);
for (int j = 0; j < ops_of_block_[*to_predict_block.get()].size(); ++j) {
for (int j = 0; j < ops_of_block_[*to_predict_block.get()].size();
++j) {
auto op = ops_of_block_[*to_predict_block.get()][j];
// std::cout << "开始run" << std::endl;
op->Run();
}
}
}
template class Executor<CPU>;
template class Executor<CPU>;
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -32,14 +32,14 @@ SOFTWARE.
#include "variable.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
template <typename Dtype> class Executor {
public:
template <typename Dtype> class Executor {
public:
Executor(const Program<Dtype> p);
std::shared_ptr<Tensor> predict(Tensor &t);
private:
private:
const framework::Program<Dtype> program_;
std::shared_ptr<ProgramDesc> to_predict_program_;
void predict(const Tensor &t, int block_id);
......@@ -47,7 +47,7 @@ private:
std::vector<std::shared_ptr<OperatorBase<Dtype>>>>
ops_of_block_;
bool use_optimize_ = false;
};
};
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
此差异已折叠。
此差异已折叠。
......@@ -19,9 +19,9 @@ limitations under the License. */
#include <string.h>
namespace paddle_mobile {
namespace framework {
namespace framework {
std::ostream &operator<<(std::ostream &os, const LoD &lod) {
std::ostream &operator<<(std::ostream &os, const LoD &lod) {
os << "{";
for (auto &v : lod) {
os << "{";
......@@ -39,10 +39,11 @@ std::ostream &operator<<(std::ostream &os, const LoD &lod) {
os << "}";
return os;
}
}
std::ostream &operator<<(std::ostream &os, const LoDTensor &t) {
// PADDLE_ENFORCE(t.type().hash_code() == typeid(float).hash_code());
std::ostream &operator<<(std::ostream &os, const LoDTensor &t) {
// PADDLE_ENFORCE(t.type().hash_code() ==
// typeid(float).hash_code());
// if (!platform::is_cpu_place(t.place())) {
// LoDTensor tt;
......@@ -65,15 +66,15 @@ std::ostream &operator<<(std::ostream &os, const LoDTensor &t) {
}
return os;
}
}
std::string LoDToString(const LoD &lod) {
std::string LoDToString(const LoD &lod) {
std::ostringstream stream;
stream << lod;
return stream.str();
}
}
LoD SliceInLevel(const LoD &in, size_t level, size_t elem_begin,
LoD SliceInLevel(const LoD &in, size_t level, size_t elem_begin,
size_t elem_end) {
// PADDLE_ENFORCE_LT(level, in.size());
// PADDLE_ENFORCE_LT(elem_end, in[level].size());
......@@ -91,7 +92,8 @@ LoD SliceInLevel(const LoD &in, size_t level, size_t elem_begin,
in_level.begin() + above_level.back() + 1);
}
for (size_t lvl = 0; lvl < res.size(); lvl++) {
// to make the first offset equals 0, all the elements minus the first
// to make the first offset equals 0, all the elements minus the
// first
// element
size_t front = res[lvl].front();
for (auto &ele : res[lvl]) {
......@@ -99,23 +101,24 @@ LoD SliceInLevel(const LoD &in, size_t level, size_t elem_begin,
}
}
return res;
}
}
LoD ToAbsOffset(const LoD &in) {
LoD ToAbsOffset(const LoD &in) {
// the lowest level stores relative offsets
if (in.empty() || in.size() == 1)
return in;
LoD result = in;
for (auto level = static_cast<int>(in.size() - 2); level >= 0; level--) {
for (auto level = static_cast<int>(in.size() - 2); level >= 0;
level--) {
for (size_t i = 0; i < in[level].size(); ++i) {
size_t index = in[level][i];
result[level][i] = result[level + 1][index];
}
}
return result;
}
}
bool operator==(const LoD &a, const LoD &b) {
bool operator==(const LoD &a, const LoD &b) {
if (a.size() != b.size()) {
return false;
}
......@@ -133,21 +136,25 @@ bool operator==(const LoD &a, const LoD &b) {
}
}
return true;
}
}
bool CheckLoD(const LoD &in, int tensor_height) {
bool CheckLoD(const LoD &in, int tensor_height) {
if (in.empty())
return true;
for (const auto &level : in) {
// check: there should be more than 2 offsets existing in each level.
// check: there should be more than 2 offsets existing in each
// level.
if (level.size() < 2)
return false;
// check: the first offset(the begin offset) of each level should be 0.
// check: the first offset(the begin offset) of each level
// should be 0.
if (level.front() != 0)
return false;
// check: all the offsets in a level should be ascending(no same items
// check: all the offsets in a level should be ascending(no same
// items
// allows).
if (!std::is_sorted(level.begin(), level.begin(), [](size_t a, size_t b) {
if (!std::is_sorted(level.begin(), level.begin(),
[](size_t a, size_t b) {
if (a < b)
return true;
return false;
......@@ -156,29 +163,34 @@ bool CheckLoD(const LoD &in, int tensor_height) {
return false;
}
}
// check: the lowest level's last offset should equals `tensor_height` if
// check: the lowest level's last offset should equals
// `tensor_height` if
// tensor_height>0.
if (tensor_height > 0 && (size_t)tensor_height != in.back().back())
return false;
// check: the higher level's last offset should equals the lower level's
// check: the higher level's last offset should equals the lower
// level's
// size-1.
// NOTE LoD store the levels from top to bottom, so the higher level goes
// NOTE LoD store the levels from top to bottom, so the higher level
// goes
// first.
for (size_t level = 0; level < in.size() - 1; level++) {
if (in[level].back() != in[level + 1].size() - 1)
return false;
}
return true;
}
}
bool CheckAbsLoD(const LoD &in, int tensor_height) {
bool CheckAbsLoD(const LoD &in, int tensor_height) {
if (in.empty())
return true;
for (const auto &level : in) {
// check: all the offsets in a level should be ascending(no same items
// check: all the offsets in a level should be ascending(no same
// items
// allows).
if (!std::is_sorted(level.begin(), level.begin(), [](size_t a, size_t b) {
if (!std::is_sorted(level.begin(), level.begin(),
[](size_t a, size_t b) {
if (a < b)
return true;
return false;
......@@ -186,11 +198,13 @@ bool CheckAbsLoD(const LoD &in, int tensor_height) {
return false;
}
// check: there should be more than 2 offsets existing in each level.
// check: there should be more than 2 offsets existing in each
// level.
if (level.size() < 2)
return false;
// check: the first offset of each level should be 0, and the last should be
// check: the first offset of each level should be 0, and the
// last should be
// the same(the height of underlying tensor).
if (level.front() != 0)
return false;
......@@ -201,20 +215,24 @@ bool CheckAbsLoD(const LoD &in, int tensor_height) {
}
}
return true;
}
}
using LoDAndOffset = std::pair<LoD, std::pair<size_t, size_t>>;
using LoDAndOffset = std::pair<LoD, std::pair<size_t, size_t>>;
LoDAndOffset GetSubLoDAndAbsoluteOffset(const LoD &lod, size_t start_idx,
size_t end_idx, size_t start_level) {
LoDAndOffset GetSubLoDAndAbsoluteOffset(const LoD &lod,
size_t start_idx,
size_t end_idx,
size_t start_level) {
LoD sub_lod;
for (size_t level_idx = start_level; level_idx < lod.size(); ++level_idx) {
for (size_t level_idx = start_level; level_idx < lod.size();
++level_idx) {
// PADDLE_ENFORCE_LE(start_idx, end_idx);
// PADDLE_ENFORCE_LT(end_idx, lod[level_idx].size());
std::vector<size_t> level_lens;
for (size_t i = start_idx; i < end_idx; ++i) {
level_lens.push_back(lod[level_idx][i + 1] - lod[level_idx][i]);
level_lens.push_back(lod[level_idx][i + 1] -
lod[level_idx][i]);
}
sub_lod.emplace_back(level_lens);
start_idx = lod[level_idx][start_idx];
......@@ -222,12 +240,13 @@ LoDAndOffset GetSubLoDAndAbsoluteOffset(const LoD &lod, size_t start_idx,
}
return LoDAndOffset{sub_lod, {start_idx, end_idx}};
}
}
void AppendLoD(LoD *lod, const LoD &lod_length) {
void AppendLoD(LoD *lod, const LoD &lod_length) {
// PADDLE_ENFORCE(
// lod->empty() || lod->size() == lod_length.size(),
// "The lod_length should has the same size with the appended lod.");
// "The lod_length should has the same size with the appended
// lod.");
if (lod->empty()) {
for (size_t i = 0; i < lod_length.size(); ++i) {
lod->emplace_back(1, 0); // size = 1, value = 0;
......@@ -240,12 +259,13 @@ void AppendLoD(LoD *lod, const LoD &lod_length) {
level.push_back(level.back() + len);
}
}
}
}
void SerializeToStream(std::ostream &os, const LoDTensor &tensor) {
void SerializeToStream(std::ostream &os, const LoDTensor &tensor) {
{ // the 1st field, uint32_t version for LoDTensor
constexpr uint32_t version = 0;
os.write(reinterpret_cast<const char *>(&version), sizeof(version));
os.write(reinterpret_cast<const char *>(&version),
sizeof(version));
}
{
// the 2st field, LoD information
......@@ -258,27 +278,31 @@ void SerializeToStream(std::ostream &os, const LoDTensor &tensor) {
os.write(reinterpret_cast<const char *>(&size), sizeof(size));
for (auto &each : lod) {
size = each.size() * sizeof(framework::LoD::value_type::value_type);
os.write(reinterpret_cast<const char *>(&size), sizeof(size));
size = each.size() *
sizeof(framework::LoD::value_type::value_type);
os.write(reinterpret_cast<const char *>(&size),
sizeof(size));
os.write(reinterpret_cast<const char *>(each.data()),
static_cast<std::streamsize>(size));
}
}
// the 3st field, Tensor
TensorToStream(os, static_cast<Tensor>(tensor));
}
}
void DeserializeFromStream(std::istream &is, LoDTensor *tensor) {
void DeserializeFromStream(std::istream &is, LoDTensor *tensor) {
{
// the 1st field, unit32_t version for LoDTensor
uint32_t version;
is.read(reinterpret_cast<char *>(&version), sizeof(version));
// PADDLE_ENFORCE_EQ(version, 0U, "Only version 0 is supported");
// PADDLE_ENFORCE_EQ(version, 0U, "Only version 0 is
// supported");
}
{
// the 2st field, LoD information
uint64_t lod_level;
is.read(reinterpret_cast<char *>(&lod_level), sizeof(lod_level));
is.read(reinterpret_cast<char *>(&lod_level),
sizeof(lod_level));
auto &lod = *tensor->mutable_lod();
lod.resize(lod_level);
for (uint64_t i = 0; i < lod_level; ++i) {
......@@ -292,7 +316,7 @@ void DeserializeFromStream(std::istream &is, LoDTensor *tensor) {
}
// the 3st filed, Tensor
TensorFromStream(is, static_cast<Tensor *>(tensor));
}
}
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -23,13 +23,15 @@ limitations under the License. */
namespace paddle_mobile {
namespace framework {
namespace framework {
/*
/*
* LoD is short for Level of Details.
*
* - in a level, each element indicates relative offset of the lower level
* - the first element should be 0 and that indicates that this sequence start
* - in a level, each element indicates relative offset of the lower
* level
* - the first element should be 0 and that indicates that this sequence
* start
* from 0
* - each sequence's begin and end(no-inclusive) is level[id, id+1]
*
......@@ -40,25 +42,25 @@ namespace framework {
* 0 2 4 7
* 0 2 5 7 10 12 15 20
*/
using LoD = std::vector<std::vector<size_t>>;
using LoD = std::vector<std::vector<size_t>>;
std::ostream &operator<<(std::ostream &os, const LoD &lod);
std::ostream &operator<<(std::ostream &os, const LoD &lod);
std::ostream &operator<<(std::ostream &os, const LoDTensor &t);
std::ostream &operator<<(std::ostream &os, const LoDTensor &t);
std::string LoDToString(const LoD &lod);
std::string LoDToString(const LoD &lod);
LoD SliceInLevel(const LoD &in, size_t level, size_t elem_begin,
LoD SliceInLevel(const LoD &in, size_t level, size_t elem_begin,
size_t elem_end);
/*
/*
* Transform an LoD from relative offsets to absolute offsets.
*/
LoD ToAbsOffset(const LoD &in);
LoD ToAbsOffset(const LoD &in);
bool operator==(const LoD &a, const LoD &b);
bool operator==(const LoD &a, const LoD &b);
/*
/*
* Check whether this lod's format is valid.
*
* ATTENTION:
......@@ -66,37 +68,41 @@ bool operator==(const LoD &a, const LoD &b);
*
* It will check two things:
*
* 1. all the offsets in a level should be ascending(no same items allows).
* 1. all the offsets in a level should be ascending(no same items
* allows).
* 2. there should be more than 2 offsets existing in each level.
* 3. the higher level's last offset should equals the lower level's size-1.
* 3. the higher level's last offset should equals the lower level's
* size-1.
* 4. the first offset(the begin offset) of each level should be 0.
* 5. the lowest level's last offset should equals `tensor_height` if
* tensor_height>0.
*/
bool CheckLoD(const LoD &in, int tensor_height = -1);
bool CheckLoD(const LoD &in, int tensor_height = -1);
/*
/*
* Check whether this absolute lod's format is valid.
*
* ATTENTION:
* - Empty lod is treated as valid.
*
* It will check two things:
* 1. all the offsets in a level should be ascending(no same items allows)
* 1. all the offsets in a level should be ascending(no same items
* allows)
* 2. there should be more than 2 offsets existing in each level.
* 3. the first offset of each level should be 0, and the last should be the
* 3. the first offset of each level should be 0, and the last should
* be the
* same(the height of underlying tensor) or `tensor_height` if
* tensor_height>0.
*/
bool CheckAbsLoD(const LoD &in, int tensor_height = -1);
bool CheckAbsLoD(const LoD &in, int tensor_height = -1);
/*
/*
* LoDTensor (Level of details Tensor)
* see https://en.wikipedia.org/wiki/Level_of_details for reference.
*/
class LoDTensor : public Tensor {
public:
class LoDTensor : public Tensor {
public:
LoDTensor() : Tensor() {}
explicit LoDTensor(const LoD &lod) : lod_(lod) {}
......@@ -110,15 +116,19 @@ public:
/*
* Get the start offset and end offset of an element from LoD.
*/
std::pair<size_t, size_t> lod_element(size_t level, size_t elem) const {
std::pair<size_t, size_t> lod_element(size_t level,
size_t elem) const {
// PADDLE_ENFORCE_LT(level, NumLevels());
// PADDLE_ENFORCE_LT(elem, NumElements(level));
return std::make_pair((lod_)[level][elem], (lod_)[level][elem + 1]);
return std::make_pair((lod_)[level][elem],
(lod_)[level][elem + 1]);
}
/*
* Number of LoDTensor's levels, each level has units of data, for example,
* in the sentence's view, article, paragraph, sentence are 3 levels.
* Number of LoDTensor's levels, each level has units of data, for
* example,
* in the sentence's view, article, paragraph, sentence are 3
* levels.
*/
size_t NumLevels() const { return lod_.size(); }
......@@ -131,11 +141,11 @@ public:
return (lod_)[level].size() - 1;
}
private:
private:
LoD lod_;
};
};
/*
/*
* Expand the `source` to fit the LoD of `lod`. For example, a `source`
* LoDTensor is
* - LoD: [0, 2]
......@@ -145,8 +155,9 @@ private:
* returns a new LoDTensor
* - [a0 a0 a0 a1 a1]
*/
template <typename T>
LoDTensor LodExpand(const LoDTensor &source, const LoD &lod, size_t level) {
template <typename T>
LoDTensor LodExpand(const LoDTensor &source, const LoD &lod,
size_t level) {
LoD abs_lod = ToAbsOffset(lod);
const auto &lod_level = lod[level];
size_t num_instances = source.dims()[0];
......@@ -161,40 +172,41 @@ LoDTensor LodExpand(const LoDTensor &source, const LoD &lod, size_t level) {
// PADDLE_ENFORCE_EQ(num_instances, lod_level.size() - 1);
for (size_t ins = 0; ins < num_instances; ins++) {
for (size_t elem = lod_level[ins]; elem < lod_level[ins + 1]; elem++) {
for (size_t elem = lod_level[ins]; elem < lod_level[ins + 1];
elem++) {
auto slice = tensor.Slice(elem, elem + 1);
TensorCopy(source.Slice(ins, ins + 1), &slice);
}
}
return tensor;
}
// Get the absolute offset of a lod[start_level][start_idx:end_idx] and
// relative length of details for every levels(i.e., [start_level: ]).
//
// For example,
// lod = [[0, 3, 4, 8], [0, 9, 10, 11, 13, 17, 19, 22, 24]]
// start_level = 0
// start_idx = 1
// end_idx = 3
//
// Returns:
// LoD = [[1, 4], [2, 4, 2, 3, 2]]
// pair<size_t, size_t> = {11, 24}
std::pair<LoD, std::pair<size_t, size_t>>
GetSubLoDAndAbsoluteOffset(const LoD &lod, size_t start_idx, size_t end_idx,
size_t start_level);
void AppendLoD(LoD *lod, const LoD &lod_length);
/*
}
// Get the absolute offset of a lod[start_level][start_idx:end_idx] and
// relative length of details for every levels(i.e., [start_level: ]).
//
// For example,
// lod = [[0, 3, 4, 8], [0, 9, 10, 11, 13, 17, 19, 22, 24]]
// start_level = 0
// start_idx = 1
// end_idx = 3
//
// Returns:
// LoD = [[1, 4], [2, 4, 2, 3, 2]]
// pair<size_t, size_t> = {11, 24}
std::pair<LoD, std::pair<size_t, size_t>>
GetSubLoDAndAbsoluteOffset(const LoD &lod, size_t start_idx,
size_t end_idx, size_t start_level);
void AppendLoD(LoD *lod, const LoD &lod_length);
/*
* Serialize/Desiralize LoDTensor to std::ostream
* You can pass ofstream or ostringstream to serilize to file
* or to a in memory string. GPU tensor will be copied to CPU.
*/
void SerializeToStream(std::ostream &os, const LoDTensor &tensor);
void SerializeToStream(std::ostream &os, const LoDTensor &tensor);
void DeserializeFromStream(std::istream &is, LoDTensor *tensor);
void DeserializeFromStream(std::istream &is, LoDTensor *tensor);
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -5,9 +5,9 @@
#include "op_desc.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
OpDesc::OpDesc(const proto::OpDesc &desc) : desc_(desc) {
OpDesc::OpDesc(const proto::OpDesc &desc) : desc_(desc) {
for (int i = 0; i < desc_.inputs_size(); ++i) {
const proto::OpDesc::Var &var = desc_.inputs(i);
std::vector<std::string> &args = inputs_[var.parameter()];
......@@ -36,24 +36,27 @@ OpDesc::OpDesc(const proto::OpDesc &desc) : desc_(desc) {
// }
}
}
}
}
const std::vector<std::string> &OpDesc::Input(const std::string &name) const {
const std::vector<std::string> &
OpDesc::Input(const std::string &name) const {
return inputs_.find(name)->second;
}
}
const std::vector<std::string> &OpDesc::Output(const std::string &name) const {
const std::vector<std::string> &
OpDesc::Output(const std::string &name) const {
return outputs_.find(name)->second;
}
}
Attribute OpDesc::GetAttr(const std::string &name) const {
Attribute OpDesc::GetAttr(const std::string &name) const {
auto it = attrs_.find(name);
return it->second;
}
}
const std::unordered_map<std::string, Attribute> &OpDesc::GetAttrMap() const {
const std::unordered_map<std::string, Attribute> &
OpDesc::GetAttrMap() const {
return attrs_;
}
}
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -23,13 +23,15 @@ SOFTWARE.
#include "paddle_mobile_object.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
class OpDesc : PaddleMobileObject {
public:
class OpDesc : PaddleMobileObject {
public:
OpDesc(const proto::OpDesc &desc);
const std::vector<std::string> &Input(const std::string &name) const;
const std::vector<std::string> &Output(const std::string &name) const;
const std::vector<std::string> &
Input(const std::string &name) const;
const std::vector<std::string> &
Output(const std::string &name) const;
Attribute GetAttr(const std::string &name) const;
const VariableNameMap &GetInputs() { return inputs_; }
......@@ -40,12 +42,12 @@ public:
const std::string &Type() { return desc_.type(); };
private:
private:
proto::OpDesc desc_;
VariableNameMap inputs_;
VariableNameMap outputs_;
AttributeMap attrs_;
};
};
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -22,23 +22,25 @@ SOFTWARE.
#include "framework.pb.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
template <typename Dtype> struct OpInfo {
template <typename Dtype> struct OpInfo {
OpCreator<Dtype> creator_;
const OpCreator<Dtype> &Creator() const {
// PADDLE_ENFORCE_NOT_NULL(creator_,
// "Operator Creator has not been registered");
// "Operator Creator has not been
// registered");
return creator_;
}
};
};
template <typename Dtype> class OpInfoMap;
template <typename Dtype> class OpInfoMap;
template <typename Dtype> static OpInfoMap<Dtype> *g_op_info_map = nullptr;
template <typename Dtype>
static OpInfoMap<Dtype> *g_op_info_map = nullptr;
template <typename Dtype> class OpInfoMap {
public:
template <typename Dtype> class OpInfoMap {
public:
static OpInfoMap &Instance() {
if (g_op_info_map<Dtype> == nullptr) {
g_op_info_map<Dtype> = new OpInfoMap();
......@@ -51,13 +53,15 @@ public:
}
void Insert(const std::string &type, const OpInfo<Dtype> &info) {
// PADDLE_ENFORCE(!Has(type), "Operator %s has been registered", type);
// PADDLE_ENFORCE(!Has(type), "Operator %s has been
// registered", type);
map_.insert({type, info});
}
const OpInfo<Dtype> &Get(const std::string &type) const {
auto op_info_ptr = GetNullable(type);
// PADDLE_ENFORCE_NOT_NULL(op_info_ptr, "Operator %s has not been
// PADDLE_ENFORCE_NOT_NULL(op_info_ptr, "Operator %s has not
// been
// registered",
// type);
return *op_info_ptr;
......@@ -80,12 +84,12 @@ public:
return &map_;
}
private:
private:
OpInfoMap() = default;
std::unordered_map<std::string, OpInfo<Dtype>> map_;
// DISABLE_COPY_AND_ASSIGN(OpInfoMap);
};
};
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -22,12 +22,14 @@ SOFTWARE.
#include "framework.pb.h"
namespace paddle_mobile {
namespace framework {
struct OpKernelType {
namespace framework {
struct OpKernelType {
struct Hash {
size_t operator()(const OpKernelType &key) const {
int data_type = static_cast<int>(key.data_type_) << LEFT_SHIFT;
int data_layout = static_cast<int>(key.data_layout_) << (LEFT_SHIFT * 2);
int data_type = static_cast<int>(key.data_type_)
<< LEFT_SHIFT;
int data_layout = static_cast<int>(key.data_layout_)
<< (LEFT_SHIFT * 2);
std::hash<int> hasher;
return hasher(data_type + data_layout);
......@@ -45,20 +47,26 @@ struct OpKernelType {
: data_type_(data_type), data_layout_(data_layout) {}
bool operator==(const OpKernelType &o) const {
return data_type_ == o.data_type_ && data_layout_ == o.data_layout_;
return data_type_ == o.data_type_ &&
data_layout_ == o.data_layout_;
}
bool operator!=(const OpKernelType &o) const { return !(*this == o); }
};
bool operator!=(const OpKernelType &o) const {
return !(*this == o);
}
};
inline bool NeedTransformLayout(const DataLayout &l, const DataLayout &r) {
return l != DataLayout::kAnyLayout && r != DataLayout::kAnyLayout && l != r;
}
inline bool NeedTransformLayout(const DataLayout &l,
const DataLayout &r) {
return l != DataLayout::kAnyLayout && r != DataLayout::kAnyLayout &&
l != r;
}
inline bool TransFromNeeded(const OpKernelType &l, const OpKernelType &r) {
inline bool TransFromNeeded(const OpKernelType &l,
const OpKernelType &r) {
return (l.data_type_ != r.data_type_) ||
NeedTransformLayout(l.data_layout_, r.data_layout_);
}
}
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -19,8 +19,8 @@ SOFTWARE.
#pragma once
namespace paddle_mobile {
namespace framework {
// this class not only make proto but also init attribute checkers.
class OpProtoAndCheckerMaker {};
} // namespace framework
namespace framework {
// this class not only make proto but also init attribute checkers.
class OpProtoAndCheckerMaker {};
} // namespace framework
} // namespace paddle_mobile
......@@ -20,10 +20,10 @@ SOFTWARE.
#include "op_info.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
template <typename Dtype>
OperatorBase<Dtype>::OperatorBase(const std::string &type,
template <typename Dtype>
OperatorBase<Dtype>::OperatorBase(const std::string &type,
const VariableNameMap &inputs,
const VariableNameMap &outputs,
const AttributeMap &attrs,
......@@ -31,15 +31,15 @@ OperatorBase<Dtype>::OperatorBase(const std::string &type,
: type_(type), inputs_(inputs), outputs_(outputs), attrs_(attrs),
scope_(scope) {
CheckAllInputOutputSet();
}
}
template <typename Dtype> void OperatorBase<Dtype>::Run() { RunImpl(); }
template <typename Dtype> void OperatorBase<Dtype>::Run() { RunImpl(); }
template <typename Dtype>
void OperatorBase<Dtype>::CheckAllInputOutputSet() const {}
template <typename Dtype>
void OperatorBase<Dtype>::CheckAllInputOutputSet() const {}
template class OperatorBase<CPU>;
template class OperatorWithKernel<CPU>;
template class OperatorBase<CPU>;
template class OperatorWithKernel<CPU>;
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -33,12 +33,13 @@ SOFTWARE.
#include "variable.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
template <typename Dtype> class OperatorBase : PaddleMobileObject {
public:
template <typename Dtype> class OperatorBase : PaddleMobileObject {
public:
OperatorBase(const std::string &type, const VariableNameMap &inputs,
const VariableNameMap &outputs, const AttributeMap &attrs,
const VariableNameMap &outputs,
const AttributeMap &attrs,
std::shared_ptr<Scope> scope);
virtual ~OperatorBase() {}
virtual void Run();
......@@ -47,39 +48,42 @@ public:
const std::string &Type() const { return type_; }
const AttributeMap &Attrs() const { return attrs_; }
protected:
protected:
std::shared_ptr<Scope> scope_;
std::string type_;
VariableNameMap inputs_;
VariableNameMap outputs_;
AttributeMap attrs_;
private:
private:
void CheckAllInputOutputSet() const;
virtual void RunImpl() const = 0;
};
};
template <typename Dtype>
class OperatorWithKernel : public OperatorBase<Dtype> {
public:
OperatorWithKernel(const std::string &type, const VariableNameMap &inputs,
const VariableNameMap &outputs, const AttributeMap &attrs,
template <typename Dtype>
class OperatorWithKernel : public OperatorBase<Dtype> {
public:
OperatorWithKernel(const std::string &type,
const VariableNameMap &inputs,
const VariableNameMap &outputs,
const AttributeMap &attrs,
std::shared_ptr<Scope> scope)
: OperatorBase<Dtype>(type, inputs, outputs, attrs, scope) {}
virtual void InferShape() const = 0;
protected:
protected:
virtual void RunImpl() const = 0;
private:
};
private:
};
template <typename Dtype, typename P> class OpKernelBase : PaddleMobileObject {
public:
template <typename Dtype, typename P>
class OpKernelBase : PaddleMobileObject {
public:
virtual void Compute(const P &para) const = 0;
virtual ~OpKernelBase() = default;
};
};
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -23,14 +23,14 @@ SOFTWARE.
namespace paddle_mobile {
class PaddleMobileObject {
public:
class PaddleMobileObject {
public:
virtual inline const std::string &ToString() {
char address[128] = {0};
sprintf(address, "%p", this);
return std::string(address);
}
private:
};
private:
};
} // namespace paddle_mobile
......@@ -17,5 +17,5 @@ SOFTWARE.
==============================================================================*/
namespace paddle_mobile {
namespace framework {}
namespace framework {}
} // namespace paddle_mobile
......@@ -24,17 +24,17 @@ SOFTWARE.
#include "scope.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
template <typename Dtype, Precision P = Precision::FP32>
class Program : PaddleMobileObject {
public:
template <typename Dtype, Precision P = Precision::FP32>
class Program : PaddleMobileObject {
public:
std::shared_ptr<ProgramDesc> originProgram;
std::shared_ptr<ProgramDesc> optimizeProgram;
std::shared_ptr<Scope> scope;
private:
};
private:
};
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -5,18 +5,18 @@
#include "program_desc.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
ProgramDesc::ProgramDesc(const proto::ProgramDesc &desc) : desc_(desc) {
ProgramDesc::ProgramDesc(const proto::ProgramDesc &desc) : desc_(desc) {
for (auto &block_desc : *desc_.mutable_blocks()) {
// new framework::BlockDesc(block_desc)
blocks_.emplace_back(std::make_shared<BlockDesc>(block_desc));
}
}
}
std::shared_ptr<BlockDesc> ProgramDesc::Block(size_t idx) {
std::shared_ptr<BlockDesc> ProgramDesc::Block(size_t idx) {
return blocks_[idx];
}
}
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -25,18 +25,20 @@ SOFTWARE.
#include "paddle_mobile_object.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
class ProgramDesc : PaddleMobileObject {
public:
class ProgramDesc : PaddleMobileObject {
public:
ProgramDesc(const proto::ProgramDesc &desc);
std::shared_ptr<BlockDesc> Block(size_t idx);
const std::vector<std::shared_ptr<BlockDesc>> &Blocks() { return blocks_; };
const std::vector<std::shared_ptr<BlockDesc>> &Blocks() {
return blocks_;
};
private:
private:
std::vector<std::shared_ptr<BlockDesc>> blocks_;
proto::ProgramDesc desc_;
};
};
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -4,15 +4,15 @@
#include <vector>
namespace paddle_mobile {
namespace framework {
namespace framework {
Scope &Scope::NewScope() const {
Scope &Scope::NewScope() const {
std::unique_lock<std::mutex> lock(mutex_);
kids_.push_back(new Scope(this));
return *kids_.back();
}
}
Variable *Scope::Var(const std::string &name) {
Variable *Scope::Var(const std::string &name) {
auto *pvar = FindVarLocally(name);
if (pvar != nullptr) {
return pvar;
......@@ -21,58 +21,59 @@ Variable *Scope::Var(const std::string &name) {
vars_[name] = pvar;
pvar->name_ = &(vars_.find(name)->first);
return pvar;
}
}
// Variable* Scope::Var(std::string* name) {
// auto var_name = string::Sprintf("%p.%d", this, vars_.size());
// if (name != nullptr) {
// *name = var_name;
// }
// return Var(var_name);
// }
// Variable* Scope::Var(std::string* name) {
// auto var_name = string::Sprintf("%p.%d", this,
// vars_.size());
// if (name != nullptr) {
// *name = var_name;
// }
// return Var(var_name);
// }
Variable *Scope::FindVar(const std::string &name) const {
Variable *Scope::FindVar(const std::string &name) const {
auto *pvar = FindVarLocally(name);
if (pvar != nullptr) {
return pvar;
}
return (parent_ == nullptr) ? nullptr : parent_->FindVar(name);
}
}
const Scope *Scope::FindScope(const Variable *var) const {
const Scope *Scope::FindScope(const Variable *var) const {
for (auto &name_var : vars_) {
if (name_var.second == var) {
return this;
}
}
return (parent_ == nullptr) ? nullptr : parent_->FindScope(var);
}
}
void Scope::DropKids() {
void Scope::DropKids() {
for (Scope *s : kids_) {
delete s;
}
kids_.clear();
}
}
std::vector<std::string> Scope::LocalVarNames() const {
std::vector<std::string> Scope::LocalVarNames() const {
std::vector<std::string> known_vars;
known_vars.reserve(vars_.size());
for (auto &name_var : vars_) {
known_vars.emplace_back(name_var.first);
}
return known_vars;
}
}
void Scope::DeleteScope(Scope *scope) const {
void Scope::DeleteScope(Scope *scope) const {
std::unique_lock<std::mutex> lock(mutex_);
auto it = std::find(kids_.begin(), kids_.end(), scope);
kids_.erase(it);
delete scope;
// deferent
}
}
void Scope::EraseVars(const std::vector<std::string> &var_names) {
void Scope::EraseVars(const std::vector<std::string> &var_names) {
std::set<std::string> var_set(var_names.begin(), var_names.end());
for (auto it = vars_.begin(); it != vars_.end();) {
if (var_set.find(it->first) != var_set.end()) {
......@@ -82,9 +83,9 @@ void Scope::EraseVars(const std::vector<std::string> &var_names) {
++it;
}
}
}
}
void Scope::Rename(const std::string &origin_name,
void Scope::Rename(const std::string &origin_name,
const std::string &new_name) const {
auto origin_it = vars_.find(origin_name);
if (origin_it == vars_.end()) {
......@@ -96,21 +97,23 @@ void Scope::Rename(const std::string &origin_name,
}
vars_[new_name] = origin_it->second;
vars_.erase(origin_it);
}
//
// std::string Scope::Rename(const std::string& origin_name) const {
// auto var_name = string::Sprintf("%p.%d", this, vars_.size());
// Rename(origin_name, var_name);
// return var_name;
// }
}
//
// std::string Scope::Rename(const std::string& origin_name)
// const {
// auto var_name = string::Sprintf("%p.%d", this,
// vars_.size());
// Rename(origin_name, var_name);
// return var_name;
// }
Variable *Scope::FindVarLocally(const std::string &name) const {
Variable *Scope::FindVarLocally(const std::string &name) const {
auto it = vars_.find(name);
if (it != vars_.end()) {
return it->second;
}
return nullptr;
}
}
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -24,9 +24,9 @@ SOFTWARE.
#include <unordered_map> //std::unordered_map
namespace paddle_mobile {
namespace framework {
class Scope {
public:
namespace framework {
class Scope {
public:
Scope() {}
~Scope() {}
......@@ -46,7 +46,8 @@ public:
const Scope *parent() const { return parent_; }
/// Find the scope or an ancestor scope that contains the given variable.
/// Find the scope or an ancestor scope that contains the given
/// variable.
const Scope *FindScope(const Variable *var) const;
void DeleteScope(Scope *scope) const;
......@@ -66,7 +67,7 @@ public:
Variable *FindVarLocally(const std::string &name) const;
private:
private:
// Call Scope::NewScope for a sub-scope.
explicit Scope(Scope const *parent) : parent_(parent) {}
......@@ -75,6 +76,6 @@ private:
Scope const *parent_{nullptr};
mutable std::mutex mutex_;
};
} // namespace framework
};
} // namespace framework
} // namespace paddle_mobile
......@@ -24,11 +24,12 @@ SOFTWARE.
#include "tensor.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
class SelectedRows {
public:
SelectedRows(const std::vector<int64_t> &rows, const int64_t &height)
class SelectedRows {
public:
SelectedRows(const std::vector<int64_t> &rows,
const int64_t &height)
: rows_(rows), height_(height) {
value_.reset(new Tensor());
}
......@@ -67,14 +68,15 @@ public:
return make_ddim(dims);
}
private:
// Notice: rows can be duplicate. We can have {0, 4, 7, 0, 5, 7, 9} here.
private:
// Notice: rows can be duplicate. We can have {0, 4, 7, 0, 5, 7, 9}
// here.
// SelectedRows are simply concated when adding together. Until a
// SelectedRows add a Tensor, will the duplicate rows be handled.
std::vector<int64_t> rows_;
std::unique_ptr<Tensor> value_{nullptr};
int64_t height_;
};
};
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -25,10 +25,10 @@ limitations under the License. */
#include "memory/t_malloc.h"
namespace paddle_mobile {
namespace framework {
template <typename... T> struct SizeOfTypeFunctor;
namespace framework {
template <typename... T> struct SizeOfTypeFunctor;
template <typename T> struct SizeOfTypeFunctor<T> {
template <typename T> struct SizeOfTypeFunctor<T> {
size_t operator()(std::type_index type) const {
if (typeid(T).hash_code() == type.hash_code()) {
return sizeof(T);
......@@ -36,14 +36,14 @@ template <typename T> struct SizeOfTypeFunctor<T> {
return 0UL;
}
}
};
};
template <> struct SizeOfTypeFunctor<> {
template <> struct SizeOfTypeFunctor<> {
size_t operator()(std::type_index type) const { return 0UL; }
};
};
template <typename HEAD, typename... TAIL>
struct SizeOfTypeFunctor<HEAD, TAIL...> {
template <typename HEAD, typename... TAIL>
struct SizeOfTypeFunctor<HEAD, TAIL...> {
size_t operator()(std::type_index type) const {
SizeOfTypeFunctor<HEAD> head;
size_t head_size = head(type);
......@@ -53,37 +53,42 @@ struct SizeOfTypeFunctor<HEAD, TAIL...> {
SizeOfTypeFunctor<TAIL...> tail;
return tail(type);
}
};
};
static inline size_t SizeOfType(std::type_index type) {
SizeOfTypeFunctor<int, float, double, int16_t, int64_t, bool, size_t> functor;
static inline size_t SizeOfType(std::type_index type) {
SizeOfTypeFunctor<int, float, double, int16_t, int64_t, bool,
size_t>
functor;
size_t size = functor(type);
// PADDLE_ENFORCE(size != 0UL, "Cannot get size of type %s", type.name());
// PADDLE_ENFORCE(size != 0UL, "Cannot get size of type %s",
// type.name());
return size;
}
}
class LoDTensor;
class LoDTensor;
class Tensor {
public:
class Tensor {
public:
Tensor() : offset_(0) {}
/*! Return a pointer to mutable memory block. */
template <typename T> inline T *data() {
check_memory_size();
// PADDLE_ENFORCE(std::is_same<T, void>::value ||
// holder_->type().hash_code() == typeid(T).hash_code(),
// holder_->type().hash_code() ==
// typeid(T).hash_code(),
// "Tensor holds the wrong type, it holds %s",
// this->holder_->type().name());
return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(holder_->ptr()) +
offset_);
return reinterpret_cast<T *>(
reinterpret_cast<uintptr_t>(holder_->ptr()) + offset_);
}
/*! Return a pointer to constant memory block. */
template <typename T> inline const T *data() const {
check_memory_size();
// PADDLE_ENFORCE(std::is_same<T, void>::value ||
// holder_->type().hash_code() == typeid(T).hash_code(),
// holder_->type().hash_code() ==
// typeid(T).hash_code(),
// "Tensor holds the wrong type, it holds %s",
// this->holder_->type().name());
......@@ -107,8 +112,10 @@ public:
holder_->set_type(type);
}
// PADDLE_ENFORCE_GE(numel(), 0,
// "When calling this method, the Tensor's numel must be
// " "equal or larger than zero. " "Please check
// "When calling this method, the Tensor's
// numel must be
// " "equal or larger than zero. " "Please
// check
// Tensor::Resize has been called first.");
int64_t size = numel() * SizeOfType(type);
/* some versions of boost::variant don't have operator!= */
......@@ -123,7 +130,8 @@ public:
inline void *mutable_data() {
// PADDLE_ENFORCE(this->holder_ != nullptr,
// "Cannot invoke mutable data if current hold nothing.");
// "Cannot invoke mutable data if current hold
// nothing.");
return mutable_data(holder_->type());
}
......@@ -163,19 +171,24 @@ public:
/**
* @brief Return a sub-tensor of the given tensor.
*
* @param[in] begin_idx The index of the start row(inclusive) to slice.
* @param[in] begin_idx The index of the start row(inclusive) to
* slice.
* The index number begins from 0.
* @param[in] end_idx The index of the end row(exclusive) to slice.
* @param[in] end_idx The index of the end row(exclusive) to
* slice.
* The index number begins from 0.
*/
inline Tensor Slice(int begin_idx, int end_idx) const {
check_memory_size();
// PADDLE_ENFORCE_GE(begin_idx, 0,
// "The start row index must be greater than 0.");
// PADDLE_ENFORCE_LE(end_idx, dims_[0], "The end row index is out of
// "The start row index must be greater than
// 0.");
// PADDLE_ENFORCE_LE(end_idx, dims_[0], "The end row index is
// out of
// bound."); PADDLE_ENFORCE_LT(
// begin_idx, end_idx,
// "The start row index must be lesser than the end row index.");
// "The start row index must be lesser than the end row
// index.");
if (dims_[0] == 1) {
return *this;
......@@ -187,14 +200,16 @@ public:
DDim dst_dims = dims_;
dst_dims[0] = end_idx - begin_idx;
dst.Resize(dst_dims);
dst.offset_ = offset_ + begin_idx * base * SizeOfType(type());
dst.offset_ =
offset_ + begin_idx * base * SizeOfType(type());
return dst;
}
}
std::type_index type() const {
// PADDLE_ENFORCE_NOT_NULL(
// holder_, "Tensor not initialized yet when
// holder_, "Tensor not initialized yet
// when
// Tensor::type() is called.");
return holder_->type();
}
......@@ -206,23 +221,29 @@ public:
inline void check_memory_size() const {
// PADDLE_ENFORCE_NOT_NULL(
// holder_, "Tensor holds no memory. Call Tensor::mutable_data
// holder_, "Tensor holds no memory. Call
// Tensor::mutable_data
// first.");
// PADDLE_ENFORCE_LE(
// numel() * SizeOfType(type()), memory_size(),
// "Tensor's dims_ is out of bound. Call Tensor::mutable_data "
// "Tensor's dims_ is out of bound. Call
// Tensor::mutable_data "
// "first to re-allocate memory.\n"
// "or maybe the required data-type mismatches the data already
// "or maybe the required data-type mismatches the data
// already
// stored.");
}
inline DataLayout layout() const { return layout_; }
inline void set_layout(const DataLayout layout) { layout_ = layout; }
inline void set_layout(const DataLayout layout) {
layout_ = layout;
}
private:
private:
/**
* @note Placeholder hides type T, so it doesn't appear as a template
* @note Placeholder hides type T, so it doesn't appear as a
* template
* parameter of Variable.
*/
struct Placeholder {
......@@ -242,15 +263,20 @@ private:
: ptr_(static_cast<uint8_t *>(memory::Alloc(size)),
memory::PODDeleter<uint8_t>()),
size_(size), type_(type) {
// PADDLE_ENFORCE_NOT_NULL(ptr_, "Insufficient %s
// PADDLE_ENFORCE_NOT_NULL(ptr_,
// "Insufficient %s
// memory to allocation.",
// (is_cpu_place(place_) ?
// "CPU" : "GPU"));
// (is_cpu_place(place_)
// ?
// "CPU" :
// "GPU"));
}
virtual size_t size() const { return size_; }
virtual void *ptr() const { return static_cast<void *>(ptr_.get()); }
virtual void *ptr() const {
return static_cast<void *>(ptr_.get());
}
virtual std::type_index type() const { return type_; }
......@@ -280,8 +306,10 @@ private:
/**
* @brief the layout of memory block, default is NHWC.
*
* @note the memory allocation order, describe how weight/data is stored
* For example, in 4-D Tensor(rank=4), there are three commonly
* @note the memory allocation order, describe how weight/data is
* stored
* For example, in 4-D Tensor(rank=4), there are three
* commonly
* used layout. They are
* NCHW, NHWC, CHWN.
* N,C,H,W for respectively the batch size, the number of
......@@ -295,17 +323,18 @@ private:
*
* @note Some of them may be slices of the others. So the offset_
* is introduced here to indicate the byte offset between
* PlaceHolder::ptr_ and where the tensor data really begins.
* PlaceHolder::ptr_ and where the tensor data really
* begins.
*/
size_t offset_;
};
};
inline Tensor ReshapeToMatrix(const Tensor &src, int num_col_dims) {
inline Tensor ReshapeToMatrix(const Tensor &src, int num_col_dims) {
Tensor res;
res.ShareDataWith(src);
res.Resize(flatten_to_2d(src.dims(), num_col_dims));
return res;
}
}
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -18,10 +18,11 @@
#include <vector>
namespace paddle_mobile {
namespace framework {
namespace framework {
void TensorCopy(const Tensor &src, Tensor *dst) {
// VLOG(3) << "TensorCopy " << src.dims() << " from " << src.place() << " to
void TensorCopy(const Tensor &src, Tensor *dst) {
// VLOG(3) << "TensorCopy " << src.dims() << " from " <<
// src.place() << " to
// "
// << dst_place;
src.check_memory_size();
......@@ -35,10 +36,11 @@ void TensorCopy(const Tensor &src, Tensor *dst) {
auto size = src.numel() * SizeOfType(src.type());
memory::Copy(dst_ptr, src_ptr, size);
}
}
void TensorCopySync(const Tensor &src, Tensor *dst) {
// VLOG(3) << "TensorCopySync " << src.dims() << " from " << src.place()
void TensorCopySync(const Tensor &src, Tensor *dst) {
// VLOG(3) << "TensorCopySync " << src.dims() << " from " <<
// src.place()
// << " to " << dst_place;
src.check_memory_size();
dst->Resize(src.dims());
......@@ -47,14 +49,15 @@ void TensorCopySync(const Tensor &src, Tensor *dst) {
auto dst_ptr = dst->mutable_data(src.type());
auto size = src.numel() * SizeOfType(src.type());
memory::Copy(dst_ptr, src_ptr, size);
}
}
template <typename Predicate> struct AnyDTypeVisitor {
template <typename Predicate> struct AnyDTypeVisitor {
Predicate predicate_;
const Tensor &tensor_;
Tensor *out_;
AnyDTypeVisitor(Predicate predicate, const Tensor &tensor, Tensor *out)
AnyDTypeVisitor(Predicate predicate, const Tensor &tensor,
Tensor *out)
: predicate_(predicate), tensor_(tensor), out_(out) {}
template <typename T> void operator()() const {
......@@ -63,16 +66,16 @@ template <typename Predicate> struct AnyDTypeVisitor {
// return any of predicate_(t) is true.
// o.device(*ctx_.eigen_device()) = predicate_(t).any();
}
};
};
template <typename Predicate>
inline void AnyImpl(Predicate predicate, const Tensor &tensor,
template <typename Predicate>
inline void AnyImpl(Predicate predicate, const Tensor &tensor,
framework::Tensor *out) {
VisitDataType(ToDataType(tensor.type()),
AnyDTypeVisitor<Predicate>(predicate, tensor, out));
}
}
template <typename Predicate> struct AnyVisitor {
template <typename Predicate> struct AnyVisitor {
const framework::Tensor &tensor_;
Predicate predicate_;
......@@ -90,47 +93,48 @@ template <typename Predicate> struct AnyVisitor {
bool GetResult(const framework::Tensor &out) const {
return *out.data<bool>();
}
};
};
template <typename Predicate>
inline bool Any(const framework::Tensor &tensor, Predicate predicate) {
template <typename Predicate>
inline bool Any(const framework::Tensor &tensor, Predicate predicate) {
AnyVisitor<Predicate> visitor(tensor, predicate);
// return platform::VisitPlace(visitor);
return visitor();
}
}
struct ContainsNANPredicate {
struct ContainsNANPredicate {
template <typename T>
auto operator()(const T &eigen_vec) const
-> decltype(std::declval<T>().isnan()) {
// Cast eigen_vector to vector of bool. true if is inf.
return eigen_vec.isnan();
}
};
};
bool TensorContainsNAN(const framework::Tensor &tensor) {
bool TensorContainsNAN(const framework::Tensor &tensor) {
ContainsNANPredicate predicate;
return Any(tensor, predicate);
}
}
struct ContainsInfPredicate {
struct ContainsInfPredicate {
template <typename T>
auto operator()(const T &eigen_vec) const
-> decltype(std::declval<T>().isinf()) {
// Cast eigen_vector to vector of bool. true if is inf.
return eigen_vec.isinf();
}
};
};
bool TensorContainsInf(const framework::Tensor &tensor) {
bool TensorContainsInf(const framework::Tensor &tensor) {
ContainsInfPredicate predicate;
return Any(tensor, predicate);
}
}
void TensorToStream(std::ostream &os, const Tensor &tensor) {
void TensorToStream(std::ostream &os, const Tensor &tensor) {
{ // the 1st field, uint32_t version
constexpr uint32_t version = 0;
os.write(reinterpret_cast<const char *>(&version), sizeof(version));
os.write(reinterpret_cast<const char *>(&version),
sizeof(version));
}
{ // the 2nd field, tensor description
// int32_t size
......@@ -149,15 +153,16 @@ void TensorToStream(std::ostream &os, const Tensor &tensor) {
{ // the 3rd field, tensor data
uint64_t size = tensor.memory_size();
auto *data_ptr = tensor.data<void>();
// PADDLE_ENFORCE(size < std::numeric_limits<std::streamsize>::max(),
// PADDLE_ENFORCE(size <
// std::numeric_limits<std::streamsize>::max(),
// "Index overflow when writing tensor");
os.write(static_cast<const char *>(data_ptr),
static_cast<std::streamsize>(size));
}
}
}
struct DeserializedDataFunctor {
struct DeserializedDataFunctor {
DeserializedDataFunctor(void **buf, Tensor *tensor)
: buf_(buf), tensor_(tensor) {}
......@@ -167,9 +172,9 @@ struct DeserializedDataFunctor {
void **buf_;
Tensor *tensor_;
};
};
void TensorFromStream(std::istream &is, framework::Tensor *tensor) {
void TensorFromStream(std::istream &is, framework::Tensor *tensor) {
uint32_t version;
is.read(reinterpret_cast<char *>(&version), sizeof(version));
// PADDLE_ENFORCE_EQ(version, 0U, "Only version 0 is supported");
......@@ -186,7 +191,8 @@ void TensorFromStream(std::istream &is, framework::Tensor *tensor) {
{ // read tensor
std::vector<int64_t> dims;
dims.reserve(static_cast<size_t>(desc.dims().size()));
std::copy(desc.dims().begin(), desc.dims().end(), std::back_inserter(dims));
std::copy(desc.dims().begin(), desc.dims().end(),
std::back_inserter(dims));
tensor->Resize(framework::make_ddim(dims));
void *buf;
......@@ -194,7 +200,7 @@ void TensorFromStream(std::istream &is, framework::Tensor *tensor) {
DeserializedDataFunctor(&buf, tensor));
is.read(static_cast<char *>(buf), tensor->memory_size());
}
}
}
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -20,39 +20,39 @@ limitations under the License. */
#include <vector>
namespace paddle_mobile {
namespace framework {
namespace framework {
void TensorCopy(const Tensor &src, Tensor *dst);
void TensorCopySync(const Tensor &src, Tensor *dst);
void TensorCopy(const Tensor &src, Tensor *dst);
void TensorCopySync(const Tensor &src, Tensor *dst);
template <typename T>
void TensorFromVector(const std::vector<T> &src, Tensor *dst);
template <typename T>
void TensorFromVector(const std::vector<T> &src, Tensor *dst);
template <typename T>
void TesnorToVector(const Tensor &src, std::vector<T> *dst);
template <typename T>
void TesnorToVector(const Tensor &src, std::vector<T> *dst);
bool TensorContainsNAN(const framework::Tensor &tensor);
bool TensorContainsInf(const framework::Tensor &tensor);
bool TensorContainsNAN(const framework::Tensor &tensor);
bool TensorContainsInf(const framework::Tensor &tensor);
void TensorToStream(std::ostream &os, const Tensor &tensor);
void TensorFromStream(std::istream &is, Tensor *tensor);
void TensorToStream(std::ostream &os, const Tensor &tensor);
void TensorFromStream(std::istream &is, Tensor *tensor);
//
// The implementation of template functions.
//
//
// The implementation of template functions.
//
template <typename T>
void TensorFromVector(const std::vector<T> &src, Tensor *dst) {
template <typename T>
void TensorFromVector(const std::vector<T> &src, Tensor *dst) {
auto src_ptr = static_cast<const void *>(src.data());
dst->Resize({static_cast<int64_t>(src.size())});
auto dst_ptr = static_cast<void *>(dst->mutable_data<T>());
auto size = src.size() * sizeof(T);
memory::Copy(dst_ptr, src_ptr, size);
}
}
template <typename T>
void TensorToVector(const Tensor &src, std::vector<T> *dst) {
template <typename T>
void TensorToVector(const Tensor &src, std::vector<T> *dst) {
auto src_ptr = static_cast<const void *>(src.data<T>());
auto size = src.numel() * sizeof(T);
......@@ -60,7 +60,7 @@ void TensorToVector(const Tensor &src, std::vector<T> *dst) {
auto dst_ptr = static_cast<void *>(dst->data());
memory::Copy(dst_ptr, src_ptr, size);
}
}
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -20,9 +20,9 @@ SOFTWARE.
namespace paddle_mobile {
namespace framework {
namespace framework {
VarDesc::VarDesc(const proto::VarDesc &desc) : desc_(desc) {}
VarDesc::VarDesc(const proto::VarDesc &desc) : desc_(desc) {}
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -22,10 +22,10 @@ SOFTWARE.
#include "paddle_mobile_object.h"
namespace paddle_mobile {
namespace framework {
namespace framework {
class VarDesc {
public:
class VarDesc {
public:
VarDesc(const proto::VarDesc &desc);
std::string Name() const { return desc_.name(); }
......@@ -68,7 +68,8 @@ public:
template <typename T>
std::vector<T> RepeatedToVector(
const google::protobuf::RepeatedField<T> &repeated_field) const {
const google::protobuf::RepeatedField<T> &repeated_field)
const {
std::vector<T> ret;
ret.reserve(repeated_field.size());
std::copy(repeated_field.begin(), repeated_field.end(),
......@@ -80,9 +81,9 @@ public:
return this->RepeatedToVector(tensor_desc().dims());
}
private:
private:
proto::VarDesc desc_;
};
};
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -23,16 +23,17 @@ SOFTWARE.
#include "variable.h"
namespace paddle_mobile {
namespace framework {
inline proto::VarType::Type ToVarType(std::type_index type) {
namespace framework {
inline proto::VarType::Type ToVarType(std::type_index type) {
if (type.hash_code() == typeid(LoDTensor).hash_code()) {
return proto::VarType_Type_LOD_TENSOR;
} else if (type.hash_code() == typeid(SelectedRows).hash_code()) {
return proto::VarType_Type_SELECTED_ROWS;
} else {
// PADDLE_THROW("ToVarType:Unsupported type %s", type.name());
// PADDLE_THROW("ToVarType:Unsupported type %s",
// type.name());
}
}
}
} // namespace framework
} // namespace framework
} // namespace paddle_mobile
......@@ -26,9 +26,9 @@ SOFTWARE.
#include <typeinfo>
namespace paddle_mobile {
namespace framework {
class Variable : public PaddleMobileObject {
public:
namespace framework {
class Variable : public PaddleMobileObject {
public:
Variable() {}
~Variable() {}
......@@ -43,7 +43,8 @@ public:
template <typename T> T *GetMutable() {
if (!IsType<T>()) {
if (*Name() == "pixel") {
// std::cout << " reset " << *Name() << std::endl;
// std::cout << " reset " << *Name() <<
// std::endl;
}
holder_.reset(new PlaceholderImp<T>(new T()));
}
......@@ -53,11 +54,12 @@ public:
template <typename T> bool IsType() const {
if (holder_) {
// printf("not null \n");
printf(" holder type : %s, this type %s \n", holder_->Type().name(),
typeid(T).name());
printf(" holder type : %s, this type %s \n",
holder_->Type().name(), typeid(T).name());
}
// std::cout << " " << holder_->Type() << " " << typeid(T) <<
// std::cout << " " << holder_->Type() << " " <<
// typeid(T) <<
// std::endl;
return holder_ != nullptr && holder_->Type() == typeid(T);
}
......@@ -68,7 +70,7 @@ public:
void SetName(const std::string *name) { name_ = name; }
private:
private:
struct Placeholder {
Placeholder() = default;
virtual ~Placeholder() = default;
......@@ -92,6 +94,6 @@ private:
std::unique_ptr<Placeholder> holder_;
friend class Scope;
const std::string *name_;
};
} // namespace framework
};
} // namespace framework
} // namespace paddle_mobile
......@@ -28,7 +28,7 @@ SOFTWARE.
namespace paddle_mobile {
void ReadBinaryFile(const std::string &filename, std::string *contents) {
void ReadBinaryFile(const std::string &filename, std::string *contents) {
std::ifstream fin(filename, std::ios::in | std::ios::binary);
fin.seekg(0, std::ios::end);
contents->clear();
......@@ -36,10 +36,10 @@ void ReadBinaryFile(const std::string &filename, std::string *contents) {
fin.seekg(0, std::ios::beg);
fin.read(&(contents->at(0)), contents->size());
fin.close();
}
}
template <typename Dtype, Precision P>
void Loader<Dtype, P>::LoadVar(framework::LoDTensor *tensor,
template <typename Dtype, Precision P>
void Loader<Dtype, P>::LoadVar(framework::LoDTensor *tensor,
const std::string &file_path) {
// std::cout << " to load " << file_path << std::endl;
......@@ -76,7 +76,8 @@ void Loader<Dtype, P>::LoadVar(framework::LoDTensor *tensor,
// 3. tensor version
uint32_t tensor_version;
is.read(reinterpret_cast<char *>(&tensor_version), sizeof(tensor_version));
is.read(reinterpret_cast<char *>(&tensor_version),
sizeof(tensor_version));
// std::cout << " tensor_version: " << tensor_version << std::endl;
// 4. tensor desc
......@@ -89,17 +90,20 @@ void Loader<Dtype, P>::LoadVar(framework::LoDTensor *tensor,
framework::proto::VarType::TensorDesc desc;
desc.ParseFromArray(buf.get(), size);
// std::cout << " desc dims size " << desc.dims().size() << std::endl;
// std::cout << " desc dims size " << desc.dims().size() <<
// std::endl;
int memory_size = 1;
for (int l = 0; l < desc.dims().size(); ++l) {
// std::cout << " dim " << l << " value: " << desc.dims()[l] <<
// std::cout << " dim " << l << " value: " << desc.dims()[l]
// <<
// std::endl;
memory_size *= desc.dims()[l];
}
std::vector<int64_t> dims;
dims.reserve(static_cast<size_t>(desc.dims().size()));
std::copy(desc.dims().begin(), desc.dims().end(), std::back_inserter(dims));
std::copy(desc.dims().begin(), desc.dims().end(),
std::back_inserter(dims));
tensor->Resize(framework::make_ddim(dims));
void *memory;
......@@ -136,15 +140,16 @@ void Loader<Dtype, P>::LoadVar(framework::LoDTensor *tensor,
// std::cout << " not support" << std::endl;
}
// std::cout << " malloc size: " << memory_size * type_size << std::endl;
// std::cout << " malloc size: " << memory_size * type_size <<
// std::endl;
is.read(static_cast<char *>(memory), memory_size * type_size);
// std::cout << " memory: " << memory << std::endl;
is.close();
};
};
template <typename Dtype, Precision P>
const framework::Program<Dtype, P>
Loader<Dtype, P>::Load(const std::string &dirname) {
template <typename Dtype, Precision P>
const framework::Program<Dtype, P>
Loader<Dtype, P>::Load(const std::string &dirname) {
std::string model_filename = dirname + "/__model__";
std::string program_desc_str;
ReadBinaryFile(model_filename, &program_desc_str);
......@@ -168,10 +173,13 @@ Loader<Dtype, P>::Load(const std::string &dirname) {
for (int i = 0; i < block->Vars().size(); ++i) {
std::shared_ptr<framework::VarDesc> var_desc = block->Vars()[i];
auto var = scope->Var(var_desc->Name());
if (var_desc->GetType() == framework::proto::VarType::LOD_TENSOR) {
if (var_desc->GetType() ==
framework::proto::VarType::LOD_TENSOR) {
if (var_desc->Persistable() &&
var_desc->GetType() != framework::proto::VarType::FEED_MINIBATCH &&
var_desc->GetType() != framework::proto::VarType::FETCH_LIST) {
var_desc->GetType() !=
framework::proto::VarType::FEED_MINIBATCH &&
var_desc->GetType() !=
framework::proto::VarType::FETCH_LIST) {
framework::LoDTensor *tensor =
var->GetMutable<framework::LoDTensor>();
// to load
......@@ -193,64 +201,79 @@ Loader<Dtype, P>::Load(const std::string &dirname) {
// std::cout << " op: " << op.type() << std::endl;
for (int m = 0; m < op.inputs_size(); ++m) {
const framework::proto::OpDesc::Var &var = op.inputs(m);
// std::cout << " input parameter: " << var.parameter() <<
// std::cout << " input parameter: " <<
// var.parameter() <<
// std::endl;
for (int n = 0; n < var.arguments().size(); ++n) {
// std::cout << " argument - " << var.arguments()[n] <<
// std::cout << " argument - " <<
// var.arguments()[n] <<
// std::endl;
}
}
for (int y = 0; y < op.outputs_size(); ++y) {
const framework::proto::OpDesc::Var &var = op.outputs(y);
// std::cout << " output parameter: " << var.parameter() <<
// std::cout << " output parameter: " <<
// var.parameter() <<
// std::endl;
for (int z = 0; z < var.arguments().size(); ++z) {
// std::cout << " argument - " << var.arguments()[z] <<
// std::cout << " argument - " <<
// var.arguments()[z] <<
// std::endl;
}
}
for (int x = 0; x < op.attrs().size(); ++x) {
const framework::proto::OpDesc_Attr attr = op.attrs()[x];
// std::cout << " attr name: " << attr.name() << std::endl;
// std::cout << " attr type: " << attr.type() << std::endl;
// std::cout << " attr name: " << attr.name() <<
// std::endl;
// std::cout << " attr type: " << attr.type() <<
// std::endl;
switch (attr.type()) {
case framework::proto::AttrType::BOOLEAN:
// std::cout << " boolen: " << attr.b() << std::endl;
// std::cout << " boolen: " << attr.b() <<
// std::endl;
break;
case framework::proto::AttrType::INT:
// std::cout << " int: " << attr.i() << std::endl;
// std::cout << " int: " << attr.i() <<
// std::endl;
break;
case framework::proto::AttrType::FLOAT:
// std::cout << " float: " << attr.f() << std::endl;
// std::cout << " float: " << attr.f() <<
// std::endl;
case framework::proto::AttrType::STRING:
// std::cout << " string: " << attr.s() << std::endl;
// std::cout << " string: " << attr.s() <<
// std::endl;
case framework::proto::AttrType::BOOLEANS:
// std::vector<bool>
// bools(attr.bools_size());
for (int y = 0; y < attr.bools_size(); ++y) {
// std::cout << " bool - " << attr.bools(y) <<
// std::cout << " bool - " <<
// attr.bools(y) <<
// std::endl;
}
case framework::proto::AttrType::LONG:
// std::cout << " long: " << attr.l() << std::endl;
// std::cout << " long: " << attr.l() <<
// std::endl;
case framework::proto::AttrType::FLOATS:
for (int y = 0; y < attr.floats_size(); ++y) {
// std::cout << " float - " << y << ": " <<
// std::cout << " float - " << y <<
// ": " <<
// attr.floats(y)
// << std::endl;
}
case framework::proto::AttrType::INTS:
for (int y = 0; y < attr.ints_size(); ++y) {
// std::cout << " int - " << y << ": " <<
// std::cout << " int - " << y << ":
// " <<
// attr.ints(y)
// << std::endl;
}
case framework::proto::AttrType::STRINGS:
for (int y = 0; y < attr.strings_size(); ++y) {
// std::cout << " string - " << y << ": " <<
// std::cout << " string - " << y <<
// ": " <<
// attr.strings(y)
// << std::endl;
}
......@@ -260,40 +283,53 @@ Loader<Dtype, P>::Load(const std::string &dirname) {
for (int k = 0; k < block.vars().size(); ++k) {
framework::proto::VarDesc var = block.vars()[k];
if (var.type().type() == framework::proto::VarType::LOD_TENSOR) {
// std::cout << " var name: " << var.name() << std::endl;
if (var.type().type() ==
framework::proto::VarType::LOD_TENSOR) {
// std::cout << " var name: " << var.name() <<
// std::endl;
const framework::proto::VarType::TensorDesc &tensor_desc =
var.type().lod_tensor().tensor();
// std::cout << " in var tensor desc dims size "
// << tensor_desc.dims().size() << std::endl;
// << tensor_desc.dims().size() <<
// std::endl;
int memory_size = 1;
for (int l = 0; l < tensor_desc.dims().size(); ++l) {
// std::cout << " var tensor desc dim " << l
// << " value: " << tensor_desc.dims()[l] <<
// << " value: " <<
// tensor_desc.dims()[l] <<
// std::endl;
}
}
if (var.persistable() &&
var.type().type() != framework::proto::VarType::FEED_MINIBATCH &&
var.type().type() != framework::proto::VarType::FETCH_LIST) {
// std::cout << " to load " << var.name() << std::endl;
var.type().type() !=
framework::proto::VarType::FEED_MINIBATCH &&
var.type().type() !=
framework::proto::VarType::FETCH_LIST) {
// std::cout << " to load " << var.name() <<
// std::endl;
std::string file_path = dirname + "/" + var.name();
std::ifstream is(file_path);
std::streampos pos = is.tellg(); // save current position
std::streampos pos =
is.tellg(); // save current position
is.seekg(0, std::ios::end);
// std::cout << " file length = " << is.tellg() << std::endl;
// std::cout << " file length = " << is.tellg() <<
// std::endl;
is.seekg(pos); // restore saved position
// 1. version
uint32_t version;
is.read(reinterpret_cast<char *>(&version), sizeof(version));
// std::cout << " version: " << version << std::endl;
is.read(reinterpret_cast<char *>(&version),
sizeof(version));
// std::cout << " version: " << version <<
// std::endl;
// 2 Lod information
uint64_t lod_level;
is.read(reinterpret_cast<char *>(&lod_level), sizeof(lod_level));
// std::cout << " load level: " << lod_level << std::endl;
is.read(reinterpret_cast<char *>(&lod_level),
sizeof(lod_level));
// std::cout << " load level: " << lod_level <<
// std::endl;
// std::cout << " lod info: " << std::endl;
for (uint64_t i = 0; i < lod_level; ++i) {
uint64_t size;
......@@ -302,29 +338,35 @@ Loader<Dtype, P>::Load(const std::string &dirname) {
is.read(reinterpret_cast<char *>(tmp.data()),
static_cast<std::streamsize>(size));
for (int j = 0; j < tmp.size(); ++j) {
// std::cout << " lod - " << tmp[j] << std::endl;
// std::cout << " lod - " << tmp[j] <<
// std::endl;
}
}
uint32_t tensor_version;
is.read(reinterpret_cast<char *>(&version), sizeof(version));
// std::cout << " tensor_version: " << tensor_version <<
is.read(reinterpret_cast<char *>(&version),
sizeof(version));
// std::cout << " tensor_version: " <<
// tensor_version <<
// std::endl;
int32_t size;
is.read(reinterpret_cast<char *>(&size), sizeof(size));
// std::cout << " tensor desc size: " << size << std::endl;
// std::cout << " tensor desc size: " << size <<
// std::endl;
std::unique_ptr<char[]> buf(new char[size]);
is.read(reinterpret_cast<char *>(buf.get()), size);
framework::proto::VarType::TensorDesc desc;
desc.ParseFromArray(buf.get(), size);
// std::cout << " desc dims size " << desc.dims().size() <<
// std::cout << " desc dims size " <<
// desc.dims().size() <<
// std::endl;
int memory_size = 1;
for (int l = 0; l < desc.dims().size(); ++l) {
// std::cout << " dim " << l << " value: " <<
// std::cout << " dim " << l << " value: "
// <<
// desc.dims()[l]
// << std::endl;
memory_size *= desc.dims()[l];
......@@ -359,14 +401,18 @@ Loader<Dtype, P>::Load(const std::string &dirname) {
break;
default:
break;
// std::cout << " not support" << std::endl;
// std::cout << " not support" <<
// std::endl;
}
// std::cout << " malloc size: " << memory_size * type_size
// std::cout << " malloc size: " << memory_size *
// type_size
// << std::endl;
void *memory = malloc(memory_size * type_size);
is.read(static_cast<char *>(memory), memory_size * type_size);
// std::cout << " memory: " << memory << std::endl;
is.read(static_cast<char *>(memory),
memory_size * type_size);
// std::cout << " memory: " << memory <<
// std::endl;
is.close();
} else {
// std::cout << " *not load "
......@@ -377,8 +423,8 @@ Loader<Dtype, P>::Load(const std::string &dirname) {
#endif
return program;
}
}
template class Loader<CPU, Precision::FP32>;
template class Loader<CPU, Precision::FP32>;
} // namespace paddle_mobile
......@@ -27,13 +27,14 @@ SOFTWARE.
namespace paddle_mobile {
template <typename Dtype, Precision P = Precision::FP32>
class Loader : PaddleMobileObject {
public:
template <typename Dtype, Precision P = Precision::FP32>
class Loader : PaddleMobileObject {
public:
const framework::Program<Dtype, P> Load(const std::string &dirname);
private:
void LoadVar(framework::LoDTensor *tensor, const std::string &file_path);
};
private:
void LoadVar(framework::LoDTensor *tensor,
const std::string &file_path);
};
} // namespace paddle_mobile
......@@ -22,30 +22,30 @@ SOFTWARE.
#include <cstring>
namespace paddle_mobile {
namespace memory {
const int MALLOC_ALIGN = 16;
namespace memory {
const int MALLOC_ALIGN = 16;
void Copy(void *dst, const void *src, size_t num) {
void Copy(void *dst, const void *src, size_t num) {
std::memcpy(dst, src, num);
};
};
void *Alloc(size_t size) {
void *Alloc(size_t size) {
size_t offset = sizeof(void *) + MALLOC_ALIGN - 1;
char *p = static_cast<char *>(malloc(offset + size));
if (!p) {
return nullptr;
}
void *r = reinterpret_cast<void *>(reinterpret_cast<size_t>(p + offset) &
(~(MALLOC_ALIGN - 1)));
void *r = reinterpret_cast<void *>(
reinterpret_cast<size_t>(p + offset) & (~(MALLOC_ALIGN - 1)));
static_cast<void **>(r)[-1] = p;
return r;
}
}
void Free(void *ptr) {
void Free(void *ptr) {
if (ptr) {
free(static_cast<void **>(ptr)[-1]);
}
}
}
} // namespace memory
} // namespace memory
} // namespace paddle_mobile
......@@ -21,15 +21,15 @@ SOFTWARE.
#include <type_traits>
namespace paddle_mobile {
namespace memory {
namespace memory {
void Copy(void *dst, const void *src, size_t num);
void Copy(void *dst, const void *src, size_t num);
void *Alloc(size_t size);
void *Alloc(size_t size);
void Free(void *ptr);
void Free(void *ptr);
/**
/**
* \brief Free memory block in one place.
*
* \note In some cases, custom deleter is used to
......@@ -37,16 +37,16 @@ void Free(void *ptr);
* std::unique_ptr<T> in tensor.h.
* static_cast
*/
template <typename T> class PODDeleter {
template <typename T> class PODDeleter {
static_assert(std::is_pod<T>::value, "T must be POD");
public:
public:
explicit PODDeleter(){};
void operator()(T *ptr) { Free(static_cast<void *>(ptr)); }
};
};
/**
/**
* \brief Free memory block in one place does not meet POD
*
* \note In some cases, custom deleter is used to
......@@ -54,11 +54,11 @@ public:
* std::unique_ptr<T> in tensor.h.
* reinterpret_cast
*/
template <typename T> class PlainDeleter {
public:
template <typename T> class PlainDeleter {
public:
explicit PlainDeleter(){};
void operator()(T *ptr) { Free(reinterpret_cast<void *>(ptr)); }
};
} // namespace memory
};
} // namespace memory
} // namespace paddle_mobile
......@@ -22,17 +22,17 @@ SOFTWARE.
#include "framework/operator.h"
namespace paddle_mobile {
namespace operators {
namespace operators {
int ConvOutputSize(int input_size, int filter_size, int dilation, int padding,
int stride) {
int ConvOutputSize(int input_size, int filter_size, int dilation,
int padding, int stride) {
const int dkernel = dilation * (filter_size - 1) + 1;
int output_size = (input_size + 2 * padding - dkernel) / stride + 1;
return output_size;
}
}
template <typename Dtype, typename T>
void ConvOp<Dtype, T>::InferShape() const {
template <typename Dtype, typename T>
void ConvOp<Dtype, T>::InferShape() const {
// std::cout << " begin get dims: " << std::endl;
auto in_dims = param_.Input()->dims();
......@@ -61,16 +61,16 @@ void ConvOp<Dtype, T>::InferShape() const {
std::vector<int64_t> output_shape({in_dims[0], filter_dims[0]});
for (size_t i = 0; i < strides.size(); ++i) {
output_shape.push_back(ConvOutputSize(in_dims[i + 2], filter_dims[i + 2],
dilations[i], paddings[i],
strides[i]));
output_shape.push_back(
ConvOutputSize(in_dims[i + 2], filter_dims[i + 2],
dilations[i], paddings[i], strides[i]));
}
framework::DDim ddim = framework::make_ddim(output_shape);
param_.Output()->Resize(ddim);
}
}
template class ConvOp<CPU, float>;
template class ConvOp<CPU, float>;
} // namespace operators
} // namespace operators
} // namespace paddle_mobile
......@@ -22,31 +22,32 @@ SOFTWARE.
#include "operators/kernel/conv_kernel.h"
namespace paddle_mobile {
namespace operators {
namespace operators {
using namespace framework;
using namespace framework;
template <typename DeviceType, typename T>
class ConvOp : public framework::OperatorWithKernel<DeviceType> {
public:
template <typename DeviceType, typename T>
class ConvOp : public framework::OperatorWithKernel<DeviceType> {
public:
ConvOp(const std::string &type, const VariableNameMap &inputs,
const VariableNameMap &outputs, const framework::AttributeMap &attrs,
const VariableNameMap &outputs,
const framework::AttributeMap &attrs,
std::shared_ptr<framework::Scope> scope)
: framework::OperatorWithKernel<DeviceType>(type, inputs, outputs, attrs,
scope),
: framework::OperatorWithKernel<DeviceType>(
type, inputs, outputs, attrs, scope),
param_(inputs, outputs, attrs, *scope) {}
using framework::OperatorWithKernel<DeviceType>::OperatorWithKernel;
void InferShape() const override;
protected:
protected:
void RunImpl() const {
operators::ConvKernel<DeviceType, T, ConvParam> kernel;
kernel.Compute(param_);
}
ConvParam param_;
};
};
} // operators
} // operators
} // paddle_mobile
......@@ -19,23 +19,27 @@ SOFTWARE.
#include "operators/kernel/conv_kernel.h"
namespace paddle_mobile {
namespace operators {
namespace operators {
bool IsExpand(const std::vector<int64_t> &filter_dim,
const std::vector<int> &strides, const std::vector<int> &paddings,
bool IsExpand(const std::vector<int64_t> &filter_dim,
const std::vector<int> &strides,
const std::vector<int> &paddings,
const std::vector<int> &dilations) {
bool filter_1 = true, strides_1 = true, padding_0 = true, dilation_1 = true;
bool filter_1 = true, strides_1 = true, padding_0 = true,
dilation_1 = true;
for (size_t j = 0; j < strides.size(); ++j) {
filter_1 = filter_1 && (static_cast<int>(filter_dim[j + 2]) == 1);
filter_1 =
filter_1 && (static_cast<int>(filter_dim[j + 2]) == 1);
strides_1 = strides_1 && (strides[j] == 1);
padding_0 = padding_0 && (paddings[j] == 0);
dilation_1 = dilation_1 && (dilations[j] == 1);
}
return !(filter_1 && strides_1 && padding_0 && dilation_1);
}
}
template <>
void ConvKernel<CPU, float, ConvParam>::Compute(const ConvParam &param) const {
template <>
void ConvKernel<CPU, float, ConvParam>::Compute(
const ConvParam &param) const {
const Tensor *input = param.Input();
std::cout << " conv param " << param << std::endl;
......@@ -57,13 +61,18 @@ void ConvKernel<CPU, float, ConvParam>::Compute(const ConvParam &param) const {
const int batch_size = static_cast<int>(input->dims()[0]);
// filter_shape_vec: {k_o, k_i, k_h, k_w} or {k_o, k_i, k_d, k_h, k_w}
std::vector<int64_t> filter_shape_vec(framework::vectorize(filter.dims()));
// output_shape_vec: {o_n, o_c, o_h, o_w} or {o_n, o_c, o_d, o_h, o_w}
std::vector<int64_t> output_shape_vec(framework::vectorize(output->dims()));
// filter_shape_vec: {k_o, k_i, k_h, k_w} or {k_o, k_i, k_d, k_h,
// k_w}
std::vector<int64_t> filter_shape_vec(
framework::vectorize(filter.dims()));
// output_shape_vec: {o_n, o_c, o_h, o_w} or {o_n, o_c, o_d, o_h,
// o_w}
std::vector<int64_t> output_shape_vec(
framework::vectorize(output->dims()));
// use col_shape in the im2col calculation
// col_shape_vec: {i_c/g, k_h, k_w, o_h, o_w} or {i_c/g, k_d, k_h, k_w, o_d,
// col_shape_vec: {i_c/g, k_h, k_w, o_h, o_w} or {i_c/g, k_d, k_h,
// k_w, o_d,
// o_h, o_w}
size_t data_dim = filter_shape_vec.size() - 2;
std::vector<int64_t> col_shape_vec(1 + 2 * data_dim);
......@@ -75,12 +84,14 @@ void ConvKernel<CPU, float, ConvParam>::Compute(const ConvParam &param) const {
framework::DDim col_shape(framework::make_ddim(col_shape_vec));
// use col_matrix_shape in the gemm calculation
// size: (i_c/g * k_h * k_w, o_h * o_w) or (i_c/g * k_d * k_h * k_w, o_d *
// size: (i_c/g * k_h * k_w, o_h * o_w) or (i_c/g * k_d * k_h * k_w,
// o_d *
// o_h * o_w)
framework::DDim col_matrix_shape =
framework::flatten_to_2d(col_shape, data_dim + 1);
bool is_expand = IsExpand(filter_shape_vec, strides, paddings, dilations);
bool is_expand =
IsExpand(filter_shape_vec, strides, paddings, dilations);
Tensor col;
// col_matrix shares the same piece of data with col,
// but will be reshaped into a two-dimensional matrix shape
......@@ -95,8 +106,8 @@ void ConvKernel<CPU, float, ConvParam>::Compute(const ConvParam &param) const {
framework::DDim input_shape = framework::slice_ddim(
input->dims(), 1, static_cast<int>(input->dims().size()));
framework::DDim filter_matrix_shape = {filter.dims()[0],
filter.numel() / filter.dims()[0]};
framework::DDim filter_matrix_shape = {
filter.dims()[0], filter.numel() / filter.dims()[0]};
filter.Resize(filter_matrix_shape);
std::cout << " input dim " << input->dims() << std::endl;
......@@ -118,10 +129,12 @@ void ConvKernel<CPU, float, ConvParam>::Compute(const ConvParam &param) const {
// device_context<DeviceContext>();
for (int i = 0; i < batch_size; i++) {
Tensor in_batch = input->Slice(i, i + 1).Resize(input_shape);
Tensor out_batch = output->Slice(i, i + 1).Resize(output_matrix_shape);
Tensor out_batch =
output->Slice(i, i + 1).Resize(output_matrix_shape);
for (int g = 0; g < groups; g++) {
Tensor in_slice = in_batch.Slice(g * in_step, (g + 1) * in_step);
Tensor in_slice =
in_batch.Slice(g * in_step, (g + 1) * in_step);
if (!is_expand) {
col.ShareDataWith(in_slice);
......@@ -130,8 +143,8 @@ void ConvKernel<CPU, float, ConvParam>::Compute(const ConvParam &param) const {
} else if (data_dim == 2U) {
// im2col
im2col(in_slice, dilations, strides,
std::vector<int>{paddings[0], paddings[1], paddings[0],
paddings[1]},
std::vector<int>{paddings[0], paddings[1],
paddings[0], paddings[1]},
&col);
} else if (data_dim == 3U) {
// vol2col
......@@ -139,15 +152,17 @@ void ConvKernel<CPU, float, ConvParam>::Compute(const ConvParam &param) const {
}
// gemm
Tensor out_slice = out_batch.Slice(g * out_step, (g + 1) * out_step);
Tensor filter_slice = filter.Slice(g * out_step, (g + 1) * out_step);
math::matmul<float>(filter_slice, false, col_matrix, false, float(1.0),
&out_slice, float(0.0));
Tensor out_slice =
out_batch.Slice(g * out_step, (g + 1) * out_step);
Tensor filter_slice =
filter.Slice(g * out_step, (g + 1) * out_step);
math::matmul<float>(filter_slice, false, col_matrix, false,
float(1.0), &out_slice, float(0.0));
}
}
}
}
template class ConvKernel<CPU, float, ConvParam>;
template class ConvKernel<CPU, float, ConvParam>;
} // namespace operators
} // namespace operators
} // namespace paddle_mobile
......@@ -25,14 +25,15 @@ SOFTWARE.
#pragma once;
namespace paddle_mobile {
namespace operators {
namespace operators {
using namespace framework;
using namespace framework;
template <typename DeviceType, typename T, typename P>
class ConvKernel : public framework::OpKernelBase<DeviceType, ConvParam> {
public:
template <typename DeviceType, typename T, typename P>
class ConvKernel
: public framework::OpKernelBase<DeviceType, ConvParam> {
public:
void Compute(const ConvParam &param) const;
};
}
};
}
}
......@@ -19,11 +19,12 @@ SOFTWARE.
#include "operators/kernel/conv_kernel.h"
namespace paddle_mobile {
namespace operators {
namespace operators {
// template<>
// void ConvKernel<FPGA, float>::Compute(const ConvParam &param) const {}
//
// template class ConvKernel<FPGA, float>;
}
// template<>
// void ConvKernel<FPGA, float>::Compute(const ConvParam &param) const
// {}
//
// template class ConvKernel<FPGA, float>;
}
}
此差异已折叠。
......@@ -17,14 +17,16 @@ limitations under the License. */
#include "framework/tensor.h"
namespace paddle_mobile {
namespace operators {
namespace math {
namespace operators {
namespace math {
/* The storage format of the coldata in the Im2ColFunctor and Col2ImFunctor. */
enum class ColFormat { kCFO = 0, kOCF = 1 };
/* The storage format of the coldata in the Im2ColFunctor and
* Col2ImFunctor. */
enum class ColFormat { kCFO = 0, kOCF = 1 };
/*
* \brief Converts the image data of three dimensions(CHW) into a colData of
/*
* \brief Converts the image data of three dimensions(CHW) into a
* colData of
* five dimensions in the Im2ColFunctor calculation,
* And in the Col2ImFunctor calculation, it is reversed.
*
......@@ -44,11 +46,15 @@ enum class ColFormat { kCFO = 0, kOCF = 1 };
* \param 4-dimension [up_pad, left_pad, down_pad, right_pad].
*
* If the template argument Format is kCFO, the shape of colData is:
* [input_channels, filter_height, filter_width, output_height, output_width]
* So, it is easy to reshape into a convolution matrix for convolution
* [input_channels, filter_height, filter_width, output_height,
* output_width]
* So, it is easy to reshape into a convolution matrix for
* convolution
* calculation based on matrix multiplication.
* The shape of convolution matrix is [height, width], where the height is equal
* input_channels * filter_height * filter_width, and the width is equal
* The shape of convolution matrix is [height, width], where the
* height is equal
* input_channels * filter_height * filter_width, and the width is
* equal
* output_height * output_width.
*
* Reshape:
......@@ -60,9 +66,12 @@ enum class ColFormat { kCFO = 0, kOCF = 1 };
* output_width]
*
* If the template argument Format is kOCF, the shape of colData is:
* [output_height, output_width, input_channels, filter_height, filter_width]
* So, it is easy to reshape into a sequence matrix for rnn calculation.
* The shape of sequence matrix is [seq_length, step_size], where the seq_length
* [output_height, output_width, input_channels, filter_height,
* filter_width]
* So, it is easy to reshape into a sequence matrix for rnn
* calculation.
* The shape of sequence matrix is [seq_length, step_size], where
* the seq_length
* is equal output_height * output_width, and the step_size is equal
* input_channels * filter_height * filter_width.
*
......@@ -74,26 +83,30 @@ enum class ColFormat { kCFO = 0, kOCF = 1 };
* filter_height,
* filter_width]
*
* \note The caller needs to ensure that imShape.inputChannels is equal to
* \note The caller needs to ensure that imShape.inputChannels is
* equal to
* colShape.inputChannels.
*/
template <ColFormat Format, typename DeviceType, typename T>
class Im2ColFunctor {
public:
void operator()(const framework::Tensor &im, const std::vector<int> &dilation,
template <ColFormat Format, typename DeviceType, typename T>
class Im2ColFunctor {
public:
void operator()(const framework::Tensor &im,
const std::vector<int> &dilation,
const std::vector<int> &stride,
const std::vector<int> &padding, framework::Tensor *col);
};
const std::vector<int> &padding,
framework::Tensor *col);
};
template <ColFormat Format, typename DeviceType, typename T>
class Col2ImFunctor {
public:
template <ColFormat Format, typename DeviceType, typename T>
class Col2ImFunctor {
public:
void operator()(const framework::Tensor &col,
const std::vector<int> &dilation,
const std::vector<int> &stride,
const std::vector<int> &padding, framework::Tensor *im);
};
const std::vector<int> &padding,
framework::Tensor *im);
};
} // namespace math
} // namespace operators
} // namespace math
} // namespace operators
} // namespace paddle_mobile
......@@ -15,65 +15,75 @@ limitations under the License. */
#include "math_function.h"
namespace paddle_mobile {
namespace operators {
namespace math {
template <>
void gemm<float>(const CBLAS_TRANSPOSE transA, const CBLAS_TRANSPOSE transB,
const int M, const int N, const int K, const float alpha,
const float *A, const float *B, const float beta, float *C) {
namespace operators {
namespace math {
template <>
void gemm<float>(const CBLAS_TRANSPOSE transA,
const CBLAS_TRANSPOSE transB, const int M,
const int N, const int K, const float alpha,
const float *A, const float *B, const float beta,
float *C) {
int lda = (transA == CblasNoTrans) ? K : M;
int ldb = (transB == CblasNoTrans) ? N : K;
int ldc = N;
cblas_sgemm(CblasRowMajor, transA, transB, M, N, K, alpha, A, lda, B, ldb,
beta, C, ldc);
}
template <>
void gemm<double>(const CBLAS_TRANSPOSE transA, const CBLAS_TRANSPOSE transB,
const int M, const int N, const int K, const double alpha,
const double *A, const double *B, const double beta,
double *C) {
cblas_sgemm(CblasRowMajor, transA, transB, M, N, K, alpha, A,
lda, B, ldb, beta, C, ldc);
}
template <>
void gemm<double>(const CBLAS_TRANSPOSE transA,
const CBLAS_TRANSPOSE transB, const int M,
const int N, const int K, const double alpha,
const double *A, const double *B,
const double beta, double *C) {
int lda = (transA == CblasNoTrans) ? K : M;
int ldb = (transB == CblasNoTrans) ? N : K;
int ldc = N;
cblas_dgemm(CblasRowMajor, transA, transB, M, N, K, alpha, A, lda, B, ldb,
beta, C, ldc);
}
template <>
void gemm<float>(const bool transA, const bool transB, const int M, const int N,
const int K, const float alpha, const float *A, const int lda,
const float *B, const int ldb, const float beta, float *C,
const int ldc) {
cblas_sgemm(CblasRowMajor, transA == false ? CblasNoTrans : CblasTrans,
transB == false ? CblasNoTrans : CblasTrans, M, N, K, alpha, A,
lda, B, ldb, beta, C, ldc);
}
template <>
void gemm<double>(const bool transA, const bool transB, const int M,
const int N, const int K, const double alpha, const double *A,
const int lda, const double *B, const int ldb,
const double beta, double *C, const int ldc) {
cblas_dgemm(CblasRowMajor, transA == false ? CblasNoTrans : CblasTrans,
transB == false ? CblasNoTrans : CblasTrans, M, N, K, alpha, A,
cblas_dgemm(CblasRowMajor, transA, transB, M, N, K, alpha, A,
lda, B, ldb, beta, C, ldc);
}
}
template <>
void matmul<float>(const framework::Tensor &matrix_a, bool trans_a,
const framework::Tensor &matrix_b, bool trans_b, float alpha,
framework::Tensor *matrix_out, float beta) {
template <>
void gemm<float>(const bool transA, const bool transB, const int M,
const int N, const int K, const float alpha,
const float *A, const int lda, const float *B,
const int ldb, const float beta, float *C,
const int ldc) {
cblas_sgemm(CblasRowMajor,
transA == false ? CblasNoTrans : CblasTrans,
transB == false ? CblasNoTrans : CblasTrans, M, N,
K, alpha, A, lda, B, ldb, beta, C, ldc);
}
template <>
void gemm<double>(const bool transA, const bool transB, const int M,
const int N, const int K, const double alpha,
const double *A, const int lda, const double *B,
const int ldb, const double beta, double *C,
const int ldc) {
cblas_dgemm(CblasRowMajor,
transA == false ? CblasNoTrans : CblasTrans,
transB == false ? CblasNoTrans : CblasTrans, M, N,
K, alpha, A, lda, B, ldb, beta, C, ldc);
}
template <>
void matmul<float>(const framework::Tensor &matrix_a, bool trans_a,
const framework::Tensor &matrix_b, bool trans_b,
float alpha, framework::Tensor *matrix_out,
float beta) {
auto dim_a = matrix_a.dims();
auto dim_b = matrix_b.dims();
auto dim_out = matrix_out->dims();
// PADDLE_ENFORCE(dim_a.size() == 2 && dim_b.size() == 2 && dim_out.size() ==
// PADDLE_ENFORCE(dim_a.size() == 2 && dim_b.size() == 2 &&
// dim_out.size() ==
// 2,
// "The input and output of matmul be matrix");
//
// PADDLE_ENFORCE(platform::is_cpu_place(matrix_a.place()) &&
// platform::is_cpu_place(matrix_b.place()) &&
// platform::is_cpu_place(matrix_b.place())
// &&
// platform::is_cpu_place(matrix_out->place()),
// "Matrix must all be in CPUPlace");
......@@ -81,26 +91,32 @@ void matmul<float>(const framework::Tensor &matrix_a, bool trans_a,
int N = dim_out[1];
int K = (trans_a == false) ? dim_a[1] : dim_a[0];
CBLAS_TRANSPOSE transA = (trans_a == false) ? CblasNoTrans : CblasTrans;
CBLAS_TRANSPOSE transB = (trans_b == false) ? CblasNoTrans : CblasTrans;
CBLAS_TRANSPOSE transA =
(trans_a == false) ? CblasNoTrans : CblasTrans;
CBLAS_TRANSPOSE transB =
(trans_b == false) ? CblasNoTrans : CblasTrans;
gemm<float>(transA, transB, M, N, K, alpha, matrix_a.data<float>(),
matrix_b.data<float>(), beta, matrix_out->data<float>());
}
gemm<float>(transA, transB, M, N, K, alpha,
matrix_a.data<float>(), matrix_b.data<float>(),
beta, matrix_out->data<float>());
}
template <>
void matmul<double>(const framework::Tensor &matrix_a, bool trans_a,
template <>
void matmul<double>(const framework::Tensor &matrix_a, bool trans_a,
const framework::Tensor &matrix_b, bool trans_b,
double alpha, framework::Tensor *matrix_out, double beta) {
double alpha, framework::Tensor *matrix_out,
double beta) {
auto dim_a = matrix_a.dims();
auto dim_b = matrix_b.dims();
auto dim_out = matrix_out->dims();
// PADDLE_ENFORCE(dim_a.size() == 2 && dim_b.size() == 2 && dim_out.size() ==
// PADDLE_ENFORCE(dim_a.size() == 2 && dim_b.size() == 2 &&
// dim_out.size() ==
// 2,
// "The input and output of matmul be matrix");
//
// PADDLE_ENFORCE(platform::is_cpu_place(matrix_a.place()) &&
// platform::is_cpu_place(matrix_b.place()) &&
// platform::is_cpu_place(matrix_b.place())
// &&
// platform::is_cpu_place(matrix_out->place()),
// "Matrix must all be in CPUPlace");
......@@ -108,13 +124,16 @@ void matmul<double>(const framework::Tensor &matrix_a, bool trans_a,
int N = dim_out[1];
int K = (trans_a == false) ? dim_a[1] : dim_a[0];
CBLAS_TRANSPOSE transA = (trans_a == false) ? CblasNoTrans : CblasTrans;
CBLAS_TRANSPOSE transB = (trans_b == false) ? CblasNoTrans : CblasTrans;
CBLAS_TRANSPOSE transA =
(trans_a == false) ? CblasNoTrans : CblasTrans;
CBLAS_TRANSPOSE transB =
(trans_b == false) ? CblasNoTrans : CblasTrans;
gemm<double>(transA, transB, M, N, K, alpha, matrix_a.data<double>(),
matrix_b.data<double>(), beta, matrix_out->data<double>());
}
gemm<double>(transA, transB, M, N, K, alpha,
matrix_a.data<double>(), matrix_b.data<double>(),
beta, matrix_out->data<double>());
}
} // namespace math
} // namespace operators
} // namespace math
} // namespace operators
} // namespace paddle_mobile
......@@ -19,24 +19,26 @@ limitations under the License. */
#include <cmath>
namespace paddle_mobile {
namespace operators {
namespace math {
template <typename T>
void gemm(const CBLAS_TRANSPOSE transA, const CBLAS_TRANSPOSE transB,
const int M, const int N, const int K, const T alpha, const T *A,
const T *B, const T beta, T *C);
template <typename T>
void gemm(const bool transA, const bool transB, const int M, const int N,
const int K, const T alpha, const T *A, const int lda, const T *B,
const int ldb, const T beta, T *C, const int ldc);
// matrix multiply with continuous memory
template <typename T>
void matmul(const framework::Tensor &matrix_a, bool trans_a,
const framework::Tensor &matrix_b, bool trans_b, T alpha,
framework::Tensor *matrix_out, T beta);
} // namespace math
} // namespace operators
namespace operators {
namespace math {
template <typename T>
void gemm(const CBLAS_TRANSPOSE transA,
const CBLAS_TRANSPOSE transB, const int M, const int N,
const int K, const T alpha, const T *A, const T *B,
const T beta, T *C);
template <typename T>
void gemm(const bool transA, const bool transB, const int M,
const int N, const int K, const T alpha, const T *A,
const int lda, const T *B, const int ldb, const T beta,
T *C, const int ldc);
// matrix multiply with continuous memory
template <typename T>
void matmul(const framework::Tensor &matrix_a, bool trans_a,
const framework::Tensor &matrix_b, bool trans_b,
T alpha, framework::Tensor *matrix_out, T beta);
} // namespace math
} // namespace operators
} // namespace paddle_mobile
此差异已折叠。
......@@ -18,21 +18,24 @@ limitations under the License. */
#include "framework/tensor.h"
namespace paddle_mobile {
namespace operators {
namespace math {
/*
* \brief Converts the feature data of four dimensions(CDHW) into a colData of
namespace operators {
namespace math {
/*
* \brief Converts the feature data of four dimensions(CDHW) into a
* colData of
* seven dimensions in the Vol2ColFunctor calculation,
* And in the Col2VolFunctor calculation, it is reversed.
*
* \param volData Vol data.
* \param volShape The shape of volData,
* [input_channels, input_depth, input_height, input_width].
* [input_channels, input_depth, input_height,
* input_width].
* \param colData Column data.
* \param colShape The shape of colData.
*
* \param dilations dilation data.
* \param 3-dimension [dilation_depth, dilation_height, dilation_width].
* \param 3-dimension [dilation_depth, dilation_height,
* dilation_width].
*
* \param strides stride data.
* \param 3-dimension [stride_depth, stride_height, stride_width].
......@@ -41,12 +44,16 @@ namespace math {
* \param 3-dimension [d_pad, h_pad, w_pad].
*
* The shape of colData is:
* [input_channels, filter_depth, filter_height, filter_width, output_depth,
* [input_channels, filter_depth, filter_height, filter_width,
* output_depth,
* output_height, output_width]
* So, it is easy to reshape into a convolution matrix for convolution
* So, it is easy to reshape into a convolution matrix for
* convolution
* calculation based on matrix multiplication.
* The shape of convolution matrix is [height, width], where the height is equal
* input_channels * filter_depth * filter_height * filter_width, and the width
* The shape of convolution matrix is [height, width], where the
* height is equal
* input_channels * filter_depth * filter_height * filter_width, and
* the width
* is equal output_depth * output_height * output_width.
*
* Reshape:
......@@ -59,25 +66,30 @@ namespace math {
* output_height,
* output_width]
*
* \note The caller needs to ensure that volShape.inputChannels is equal to
* \note The caller needs to ensure that volShape.inputChannels is
* equal to
* colShape.inputChannels.
*/
using Tensor = paddle_mobile::framework::Tensor;
using Tensor = paddle_mobile::framework::Tensor;
template <typename DeviceType, typename T> class Vol2ColFunctor {
public:
void operator()(const Tensor &vol, const std::vector<int> &dilations,
template <typename DeviceType, typename T> class Vol2ColFunctor {
public:
void operator()(const Tensor &vol,
const std::vector<int> &dilations,
const std::vector<int> &strides,
const std::vector<int> &paddings, Tensor *col) const;
};
const std::vector<int> &paddings,
Tensor *col) const;
};
template <typename DeviceType, typename T> class Col2VolFunctor {
public:
void operator()(const Tensor &col, const std::vector<int> &dilations,
template <typename DeviceType, typename T> class Col2VolFunctor {
public:
void operator()(const Tensor &col,
const std::vector<int> &dilations,
const std::vector<int> &strides,
const std::vector<int> &paddings, Tensor *vol) const;
};
const std::vector<int> &paddings,
Tensor *vol) const;
};
} // namespace math
} // namespace operators
} // namespace math
} // namespace operators
} // namespace paddle_mobile
......@@ -19,25 +19,26 @@ SOFTWARE.
#include "op_param.h"
namespace paddle_mobile {
namespace operators {
namespace operators {
std::ostream &operator<<(std::ostream &os, const ConvParam &conv_param) {
std::ostream &operator<<(std::ostream &os,
const ConvParam &conv_param) {
os << "parameter of conv: " << std::endl;
os << " stride: "
<< " (" << conv_param.Strides()[0] << conv_param.Strides()[1] << ") "
<< std::endl;
<< " (" << conv_param.Strides()[0] << conv_param.Strides()[1]
<< ") " << std::endl;
os << " paddings: "
<< " (" << conv_param.Paddings()[0] << conv_param.Paddings()[1] << ") "
<< std::endl;
<< " (" << conv_param.Paddings()[0] << conv_param.Paddings()[1]
<< ") " << std::endl;
os << " dilations: "
<< " (" << conv_param.Dilations()[0] << conv_param.Dilations()[1] << ") "
<< std::endl;
<< " (" << conv_param.Dilations()[0] << conv_param.Dilations()[1]
<< ") " << std::endl;
os << " groups: " << conv_param.Groups() << std::endl;
os << " input dims: " << conv_param.Input()->dims() << std::endl;
os << " filter dims: " << conv_param.Filter()->dims() << std::endl;
os << " output dims: " << conv_param.Output()->dims() << std::endl;
return os;
}
}
} // namespace operators
} // namespace operators
} // namespace paddle_mobile
此差异已折叠。
此差异已折叠。
......@@ -17,7 +17,7 @@ limitations under the License. */
// Disable the copy and assignment operator for a class.
#ifndef DISABLE_COPY_AND_ASSIGN
#define DISABLE_COPY_AND_ASSIGN(classname) \
private: \
private: \
classname(const classname &) = delete; \
classname(classname &&) = delete; \
classname &operator=(const classname &) = delete; \
......
此差异已折叠。
#!/bin/bash
set -e
readonly VERSION="version 3."
version=$(clang-format -version)
if ! [[ $version == *"$VERSION"* ]]; then
echo "clang-format version check failed."
echo "a version contains '$VERSION' is needed, but get '$version'"
echo "you can install the right version, and make an soft-link to '\$PATH' env"
exit -1
fi
clang-format $@
此差异已折叠。
#!/bin/bash
TOTAL_ERRORS=0
#iclang-tidy *.[ch]pp -checks=*
# The trick to remove deleted files: https://stackoverflow.com/a/2413151
for file in $(git diff --cached --name-status | awk '$1 != "D" {print $2}'|grep -v ".pb." | grep -v "third-party/"); do
cpplint $file
TOTAL_ERRORS=$(expr $TOTAL_ERRORS + $?);
done
exit $TOTAL_ERRORS
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册