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