提交 8f3f7d9c 编写于 作者: 李寅

Merge branch 'neon' into 'master'

Add Neon device

See merge request !4
...@@ -12,8 +12,13 @@ ...@@ -12,8 +12,13 @@
namespace mace { namespace mace {
// 16 bytes = 32 * 4 (Neon) #ifdef __ANDROID__
// 16 bytes = 128 bits = 32 * 4 (Neon)
constexpr size_t kMaceAlignment = 16; constexpr size_t kMaceAlignment = 16;
#else
// 32 bytes = 256 bits (AVX512)
constexpr size_t kMaceAlignment = 32;
#endif
class Allocator { class Allocator {
public: public:
...@@ -41,27 +46,20 @@ class CPUAllocator: public Allocator { ...@@ -41,27 +46,20 @@ class CPUAllocator: public Allocator {
void* data = nullptr; void* data = nullptr;
#ifdef __ANDROID__ #ifdef __ANDROID__
data = memalign(kMaceAlignment, nbytes); data = memalign(kMaceAlignment, nbytes);
#elif defined(_MSC_VER)
data = _aligned_malloc(nbytes, kMaceAlignment);
#else #else
CHECK(posix_memalign(&data, kMaceAlignment, nbytes) == 0); CHECK(posix_memalign(&data, kMaceAlignment, nbytes) == 0);
#endif #endif
CHECK_NOTNULL(data); CHECK_NOTNULL(data);
// TODO(heliangliang) This should be avoided sometimes
memset(data, 0, nbytes); memset(data, 0, nbytes);
return data; return data;
} }
#ifdef _MSC_VER void Delete(void* data) override {
void Delete(void* data) {
_aligned_free(data);
}
#else
void Delete(void* data) {
free(data); free(data);
} }
#endif
void CopyBytes(void* dst, const void* src, size_t size) { void CopyBytes(void* dst, const void* src, size_t size) override {
memcpy(dst, src, size); memcpy(dst, src, size);
} }
}; };
...@@ -80,6 +78,11 @@ struct DeviceContext<DeviceType::CPU> { ...@@ -80,6 +78,11 @@ struct DeviceContext<DeviceType::CPU> {
static Allocator* allocator() { return cpu_allocator(); } static Allocator* allocator() { return cpu_allocator(); }
}; };
template <>
struct DeviceContext<DeviceType::NEON> {
static Allocator* allocator() { return cpu_allocator(); }
};
Allocator* GetDeviceAllocator(DeviceType type); Allocator* GetDeviceAllocator(DeviceType type);
} // namespace mace } // namespace mace
......
...@@ -18,6 +18,13 @@ MACE_DEFINE_REGISTRY( ...@@ -18,6 +18,13 @@ MACE_DEFINE_REGISTRY(
Workspace*); Workspace*);
MACE_REGISTER_DEVICE_TYPE(DeviceType::CPU, CPUOperatorRegistry); MACE_REGISTER_DEVICE_TYPE(DeviceType::CPU, CPUOperatorRegistry);
MACE_DEFINE_REGISTRY(
NEONOperatorRegistry,
OperatorBase,
const OperatorDef&,
Workspace*);
MACE_REGISTER_DEVICE_TYPE(DeviceType::NEON, CPUOperatorRegistry);
unique_ptr<OperatorBase> CreateOperator( unique_ptr<OperatorBase> CreateOperator(
const OperatorDef& operator_def, const OperatorDef& operator_def,
Workspace* ws, Workspace* ws,
...@@ -33,4 +40,4 @@ OperatorBase::OperatorBase(const OperatorDef &operator_def, Workspace *ws) ...@@ -33,4 +40,4 @@ OperatorBase::OperatorBase(const OperatorDef &operator_def, Workspace *ws)
} }
} // namespace mace } // namespace mace
\ No newline at end of file
...@@ -105,7 +105,7 @@ class Operator : public OperatorBase { ...@@ -105,7 +105,7 @@ class Operator : public OperatorBase {
DataTypeToEnum<T>::v()))); DataTypeToEnum<T>::v())));
} }
} }
virtual bool Run() = 0; virtual bool Run() override = 0;
~Operator() noexcept override {} ~Operator() noexcept override {}
}; };
...@@ -145,6 +145,17 @@ MACE_DECLARE_REGISTRY( ...@@ -145,6 +145,17 @@ MACE_DECLARE_REGISTRY(
#define REGISTER_CPU_OPERATOR(name, ...) \ #define REGISTER_CPU_OPERATOR(name, ...) \
MACE_REGISTER_CLASS(CPUOperatorRegistry, name, __VA_ARGS__) MACE_REGISTER_CLASS(CPUOperatorRegistry, name, __VA_ARGS__)
MACE_DECLARE_REGISTRY(
NEONOperatorRegistry,
OperatorBase,
const OperatorDef&,
Workspace*);
#define REGISTER_NEON_OPERATOR_CREATOR(key, ...) \
MACE_REGISTER_CREATOR(NEONOperatorRegistry, key, __VA_ARGS__)
#define REGISTER_NEON_OPERATOR(name, ...) \
MACE_REGISTER_CLASS(NEONOperatorRegistry, name, __VA_ARGS__)
unique_ptr<OperatorBase> CreateOperator( unique_ptr<OperatorBase> CreateOperator(
const OperatorDef &operator_def, const OperatorDef &operator_def,
Workspace *ws, Workspace *ws,
......
...@@ -23,6 +23,23 @@ bool ReluOp<DeviceType::CPU, float>::Run() { ...@@ -23,6 +23,23 @@ bool ReluOp<DeviceType::CPU, float>::Run() {
return true; return true;
} }
template <>
bool ReluOp<DeviceType::NEON, float>::Run() {
const Tensor* X = Input(0);
Tensor* Y = Output(0);
Y->ResizeLike(X);
const float* Xdata = X-> data<float>();
float* Ydata = Y->mutable_data<float>();
for (int i = 0; i < X->size(); ++i) {
Ydata[i] = std::max(Xdata[i], 0.f);
VLOG(0) << i << ": " << Xdata[i] << " " << Ydata[i];
}
return true;
}
REGISTER_CPU_OPERATOR(Relu, ReluOp<DeviceType::CPU, float>); REGISTER_CPU_OPERATOR(Relu, ReluOp<DeviceType::CPU, float>);
REGISTER_NEON_OPERATOR(Relu, ReluOp<DeviceType::NEON, float>);
} // namespace mace } // namespace mace
...@@ -3,8 +3,9 @@ syntax = "proto2"; ...@@ -3,8 +3,9 @@ syntax = "proto2";
package mace; package mace;
enum DeviceType { enum DeviceType {
CPU = 0; // In default, we will use CPU. CPU = 0; // In default, we will use CPU.
GPU = 1; NEON = 1;
OPENCL = 2;
} }
enum DataType { enum DataType {
...@@ -70,4 +71,4 @@ message NetDef { ...@@ -70,4 +71,4 @@ message NetDef {
optional string version = 3; optional string version = 3;
repeated Argument arg = 4; repeated Argument arg = 4;
repeated TensorProto tensors = 5; repeated TensorProto tensors = 5;
} }
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册