From f812de2cce882dbfa84f0696e466aa8ef9de30a0 Mon Sep 17 00:00:00 2001 From: liaogang Date: Sat, 15 Jul 2017 01:36:27 +0800 Subject: [PATCH 01/24] ENH: unify PADDLE_ENFORCE --- paddle/framework/CMakeLists.txt | 1 - paddle/framework/attr_checker.h | 2 +- paddle/framework/enforce.h | 69 ------------------ paddle/framework/enforce_test.cc | 35 --------- paddle/framework/op_registry_test.cc | 6 +- paddle/framework/tensor.h | 2 +- paddle/framework/tensor_test.cc | 2 +- paddle/memory/detail/system_allocator.cc | 5 +- paddle/platform/CMakeLists.txt | 2 + paddle/platform/cpu_info.cc | 1 - paddle/platform/device_context.h | 53 ++++++-------- paddle/platform/dynload/dynamic_loader.cc | 2 +- paddle/platform/error.h | 87 ----------------------- paddle/platform/gpu_info.cc | 10 +-- 14 files changed, 39 insertions(+), 238 deletions(-) delete mode 100644 paddle/framework/enforce.h delete mode 100644 paddle/framework/enforce_test.cc delete mode 100644 paddle/platform/error.h diff --git a/paddle/framework/CMakeLists.txt b/paddle/framework/CMakeLists.txt index 8415ce67e9..272649effc 100644 --- a/paddle/framework/CMakeLists.txt +++ b/paddle/framework/CMakeLists.txt @@ -5,7 +5,6 @@ nv_test(dim_test SRCS dim_test.cu DEPS ddim) cc_test(tensor_test SRCS tensor_test.cc DEPS ddim) cc_test(variable_test SRCS variable_test.cc) cc_test(scope_test SRCS scope_test.cc) -cc_test(enforce_test SRCS enforce_test.cc) proto_library(attr_type SRCS attr_type.proto) proto_library(op_proto SRCS op_proto.proto DEPS attr_type) cc_test(op_proto_test SRCS op_proto_test.cc DEPS op_proto protobuf) diff --git a/paddle/framework/attr_checker.h b/paddle/framework/attr_checker.h index c0c33d8114..b527539d53 100644 --- a/paddle/framework/attr_checker.h +++ b/paddle/framework/attr_checker.h @@ -5,7 +5,7 @@ #include #include #include -#include "paddle/framework/enforce.h" +#include "paddle/platform/enforce.h" namespace paddle { namespace framework { diff --git a/paddle/framework/enforce.h b/paddle/framework/enforce.h deleted file mode 100644 index 56cb7f9564..0000000000 --- a/paddle/framework/enforce.h +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. */ - -#pragma once -#include -#include -#include - -namespace paddle { -namespace framework { - -/** - * @brief Enforce exception. Inherits std::exception - * - * All enforce condition not met, will throw an EnforceNotMet exception. - */ -class EnforceNotMet : public std::exception { - public: - EnforceNotMet(const std::string& msg, const char* file, int fileline) { - std::ostringstream sout; - sout << msg << " at [" << file << ":" << fileline << "];"; - all_msg_ = sout.str(); - } - - const char* what() const noexcept override { return all_msg_.c_str(); } - - private: - std::string all_msg_; -}; - -// From https://stackoverflow.com/questions/30130930/ -// __buildin_expect is in C++ 11 standard. Since the condition which enforced -// should be true in most situation, it will make the compiler generate faster -// code by adding `UNLIKELY` macro. -#define UNLIKELY(condition) __builtin_expect(static_cast(condition), 0) - -/** - * @brief Throw a EnforceNotMet exception, automatically filled __FILE__ & - * __LINE__ - * - * This macro take __VA_ARGS__, user can pass any type if that type can - * serialize to std::ostream - */ -#define PADDLE_THROW(...) \ - do { \ - throw ::paddle::framework::EnforceNotMet( \ - ::paddle::string::Sprintf(__VA_ARGS__), __FILE__, __LINE__); \ - } while (0) - -/** - * @brief Enforce a condition, otherwise throw an EnforceNotMet - */ -#define PADDLE_ENFORCE(condition, ...) \ - do { \ - if (UNLIKELY(!(condition))) { \ - PADDLE_THROW(__VA_ARGS__); \ - } \ - } while (0) - -} // namespace framework -} // namespace paddle diff --git a/paddle/framework/enforce_test.cc b/paddle/framework/enforce_test.cc deleted file mode 100644 index f8da1a192f..0000000000 --- a/paddle/framework/enforce_test.cc +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. */ - -#include -#include - -TEST(ENFORCE, OK) { - PADDLE_ENFORCE(true, "Enforce is ok %d now %f", 123, 0.345); - size_t val = 1; - const size_t limit = 10; - PADDLE_ENFORCE(val < limit, "Enforce is OK too"); -} - -TEST(ENFORCE, FAILED) { - bool in_catch = false; - try { - PADDLE_ENFORCE(false, "Enforce is not ok %d at all", 123); - } catch (paddle::framework::EnforceNotMet err) { - in_catch = true; - std::string msg = "Enforce is not ok 123 at all"; - const char* what = err.what(); - for (size_t i = 0; i < msg.length(); ++i) { - ASSERT_EQ(what[i], msg[i]); - } - } - ASSERT_TRUE(in_catch); -} \ No newline at end of file diff --git a/paddle/framework/op_registry_test.cc b/paddle/framework/op_registry_test.cc index 4791d4aaab..0a93655728 100644 --- a/paddle/framework/op_registry_test.cc +++ b/paddle/framework/op_registry_test.cc @@ -91,7 +91,7 @@ TEST(OpRegistry, IllegalAttr) { try { paddle::framework::OperatorPtr op __attribute__((unused)) = paddle::framework::OpRegistry::CreateOp(op_desc); - } catch (paddle::framework::EnforceNotMet err) { + } catch (paddle::platform::EnforceNotMet err) { caught = true; std::string msg = "larger_than check fail"; const char* err_msg = err.what(); @@ -138,7 +138,7 @@ TEST(OpRegistry, CustomChecker) { try { paddle::framework::OperatorPtr op __attribute__((unused)) = paddle::framework::OpRegistry::CreateOp(op_desc); - } catch (paddle::framework::EnforceNotMet err) { + } catch (paddle::platform::EnforceNotMet err) { caught = true; std::string msg = "Attribute 'test_attr' is required!"; const char* err_msg = err.what(); @@ -157,7 +157,7 @@ TEST(OpRegistry, CustomChecker) { try { paddle::framework::OperatorPtr op __attribute__((unused)) = paddle::framework::OpRegistry::CreateOp(op_desc); - } catch (paddle::framework::EnforceNotMet err) { + } catch (paddle::platform::EnforceNotMet err) { caught = true; std::string msg = "'test_attr' must be even!"; const char* err_msg = err.what(); diff --git a/paddle/framework/tensor.h b/paddle/framework/tensor.h index 62e0710a82..5fdbb4f07a 100644 --- a/paddle/framework/tensor.h +++ b/paddle/framework/tensor.h @@ -18,7 +18,7 @@ limitations under the License. */ #include #include #include "paddle/framework/ddim.h" -#include "paddle/framework/enforce.h" +#include "paddle/platform/enforce.h" #include "paddle/memory/memory.h" #include "paddle/platform/place.h" diff --git a/paddle/framework/tensor_test.cc b/paddle/framework/tensor_test.cc index 255f69372f..34ea380b4e 100644 --- a/paddle/framework/tensor_test.cc +++ b/paddle/framework/tensor_test.cc @@ -33,7 +33,7 @@ TEST(Tensor, DataAssert) { bool caught = false; try { src_tensor.data(); - } catch (paddle::framework::EnforceNotMet err) { + } catch (paddle::platform::EnforceNotMet err) { caught = true; std::string msg = "Tenosr holds no memory. Call Tensor::mutable_data first."; diff --git a/paddle/memory/detail/system_allocator.cc b/paddle/memory/detail/system_allocator.cc index 1579174b1a..f61e67a329 100644 --- a/paddle/memory/detail/system_allocator.cc +++ b/paddle/memory/detail/system_allocator.cc @@ -14,7 +14,7 @@ limitations under the License. */ #include "paddle/memory/detail/system_allocator.h" #include "paddle/platform/assert.h" -#include "paddle/platform/error.h" +#include "paddle/platform/enforce.h" #include "paddle/platform/gpu_info.h" #include // for malloc and free @@ -128,8 +128,7 @@ void GPUAllocator::Free(void* p, size_t size, size_t index) { // process is terminating, in which case we don't care if // cudaFree succeeds. if (err != cudaErrorCudartUnloading) { - platform::throw_on_error(err, - "cudaFree{Host} failed in GPUAllocator::Free."); + PADDLE_ENFORCE(err, "cudaFree{Host} failed in GPUAllocator::Free."); } } diff --git a/paddle/platform/CMakeLists.txt b/paddle/platform/CMakeLists.txt index 6ac4035c0f..bd77bb7daa 100644 --- a/paddle/platform/CMakeLists.txt +++ b/paddle/platform/CMakeLists.txt @@ -8,6 +8,8 @@ cc_test(place_test SRCS place_test.cc DEPS place glog gflags) add_subdirectory(dynload) +cc_test(enforce_test SRCS enforce_test.cc) + IF(WITH_GPU) set(GPU_CTX_DEPS dynload_cuda dynamic_loader) ELSE() diff --git a/paddle/platform/cpu_info.cc b/paddle/platform/cpu_info.cc index 1905cfeee6..f2cbd863cf 100644 --- a/paddle/platform/cpu_info.cc +++ b/paddle/platform/cpu_info.cc @@ -22,7 +22,6 @@ limitations under the License. */ #endif #include "gflags/gflags.h" -#include "paddle/platform/error.h" DEFINE_double(fraction_of_cpu_memory_to_use, 1, "Default use 100% of CPU memory for PaddlePaddle," diff --git a/paddle/platform/device_context.h b/paddle/platform/device_context.h index 51c8e13913..d2569fdc91 100644 --- a/paddle/platform/device_context.h +++ b/paddle/platform/device_context.h @@ -11,7 +11,7 @@ limitations under the License. */ #pragma once -#include "paddle/framework/enforce.h" +#include "paddle/platform/enforce.h" #ifndef PADDLE_ONLY_CPU #include "paddle/platform/dynload/cublas.h" #include "paddle/platform/dynload/cudnn.h" @@ -74,8 +74,7 @@ class CUDADeviceContext : public DeviceContext { public: explicit CUDADeviceContext(const GPUPlace gpu_place) : gpu_place_(gpu_place) { GPUPlaceGuard guard(gpu_place_); - paddle::platform::throw_on_error(cudaStreamCreate(&stream_), - "cudaStreamCreate failed"); + PADDLE_ENFORCE(cudaStreamCreate(&stream_), "cudaStreamCreate failed"); eigen_stream_.reset(new Eigen::CudaStreamDevice(&stream_)); eigen_device_.reset(new Eigen::GpuDevice(eigen_stream_.get())); } @@ -86,8 +85,8 @@ class CUDADeviceContext : public DeviceContext { } void Wait() { - paddle::platform::throw_on_error(cudaStreamSynchronize(stream_), - "cudaStreamSynchronize failed"); + PADDLE_ENFORCE(cudaStreamSynchronize(stream_), + "cudaStreamSynchronize failed"); } cudaStream_t stream() { return stream_; } @@ -97,12 +96,11 @@ class CUDADeviceContext : public DeviceContext { cublasHandle_t cublas_handle() { if (!blas_handle_) { GPUPlaceGuard guard(gpu_place_); - PADDLE_ENFORCE(paddle::platform::dynload::cublasCreate(&blas_handle_) == - CUBLAS_STATUS_SUCCESS, + PADDLE_ENFORCE(paddle::platform::dynload::cublasCreate(&blas_handle_), "cublasCreate failed"); - PADDLE_ENFORCE(paddle::platform::dynload::cublasSetStream( - blas_handle_, stream_) == CUBLAS_STATUS_SUCCESS, - "cublasSetStream failed"); + PADDLE_ENFORCE( + paddle::platform::dynload::cublasSetStream(blas_handle_, stream_), + "cublasSetStream failed"); } return blas_handle_; } @@ -110,12 +108,11 @@ class CUDADeviceContext : public DeviceContext { cudnnHandle_t cudnn_handle() { if (!dnn_handle_) { GPUPlaceGuard guard(gpu_place_); - PADDLE_ENFORCE(paddle::platform::dynload::cudnnCreate(&dnn_handle_) == - CUDNN_STATUS_SUCCESS, + PADDLE_ENFORCE(paddle::platform::dynload::cudnnCreate(&dnn_handle_), "cudnnCreate failed"); - PADDLE_ENFORCE(paddle::platform::dynload::cudnnSetStream( - dnn_handle_, stream_) == CUDNN_STATUS_SUCCESS, - "cudnnSetStream failed"); + PADDLE_ENFORCE( + paddle::platform::dynload::cudnnSetStream(dnn_handle_, stream_), + "cudnnSetStream failed"); } return dnn_handle_; } @@ -124,16 +121,15 @@ class CUDADeviceContext : public DeviceContext { if (!rand_generator_) { GPUPlaceGuard guard(gpu_place_); PADDLE_ENFORCE(paddle::platform::dynload::curandCreateGenerator( - &rand_generator_, CURAND_RNG_PSEUDO_DEFAULT) == - CURAND_STATUS_SUCCESS, + &rand_generator_, CURAND_RNG_PSEUDO_DEFAULT), "curandCreateGenerator failed"); PADDLE_ENFORCE( paddle::platform::dynload::curandSetPseudoRandomGeneratorSeed( - rand_generator_, random_seed_) == CURAND_STATUS_SUCCESS, + rand_generator_, random_seed_), "curandSetPseudoRandomGeneratorSeed failed"); - PADDLE_ENFORCE(paddle::platform::dynload::curandSetStream( - rand_generator_, stream_) == CURAND_STATUS_SUCCESS, - "curandSetStream failed"); + PADDLE_ENFORCE( + paddle::platform::dynload::curandSetStream(rand_generator_, stream_), + "curandSetStream failed"); } return rand_generator_; } @@ -141,26 +137,23 @@ class CUDADeviceContext : public DeviceContext { ~CUDADeviceContext() { Wait(); if (blas_handle_) { - PADDLE_ENFORCE(paddle::platform::dynload::cublasDestroy(blas_handle_) == - CUBLAS_STATUS_SUCCESS, + PADDLE_ENFORCE(paddle::platform::dynload::cublasDestroy(blas_handle_), "cublasDestroy failed"); } if (dnn_handle_) { - PADDLE_ENFORCE(paddle::platform::dynload::cudnnDestroy(dnn_handle_) == - CUDNN_STATUS_SUCCESS, + PADDLE_ENFORCE(paddle::platform::dynload::cudnnDestroy(dnn_handle_), "cudnnDestroy failed"); } if (rand_generator_) { - PADDLE_ENFORCE(paddle::platform::dynload::curandDestroyGenerator( - rand_generator_) == CURAND_STATUS_SUCCESS, - "curandDestroyGenerator failed"); + PADDLE_ENFORCE( + paddle::platform::dynload::curandDestroyGenerator(rand_generator_), + "curandDestroyGenerator failed"); } eigen_stream_.reset(); eigen_device_.reset(); - paddle::platform::throw_on_error(cudaStreamDestroy(stream_), - "cudaStreamDestroy failed"); + PADDLE_ENFORCE(cudaStreamDestroy(stream_), "cudaStreamDestroy failed"); } private: diff --git a/paddle/platform/dynload/dynamic_loader.cc b/paddle/platform/dynload/dynamic_loader.cc index dd914e006d..ae9a0a982c 100644 --- a/paddle/platform/dynload/dynamic_loader.cc +++ b/paddle/platform/dynload/dynamic_loader.cc @@ -19,7 +19,7 @@ limitations under the License. */ #include #include "gflags/gflags.h" #include "glog/logging.h" -#include "paddle/framework/enforce.h" +#include "paddle/platform/enforce.h" DEFINE_string(cudnn_dir, "", "Specify path for loading libcudnn.so. For instance, " diff --git a/paddle/platform/error.h b/paddle/platform/error.h deleted file mode 100644 index 93424bb610..0000000000 --- a/paddle/platform/error.h +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#include -#include -#include - -#ifndef PADDLE_ONLY_CPU - -#include -#include -#include -#include -#include - -#endif // PADDLE_ONLY_CPU - -namespace paddle { -namespace platform { - -#ifndef PADDLE_ONLY_CPU - -inline void throw_on_error(cudaError_t e, const char* message) { - if (e) { - throw thrust::system_error(e, thrust::cuda_category(), message); - } -} - -inline void throw_on_error(curandStatus_t stat, const char* message) { - if (stat != CURAND_STATUS_SUCCESS) { - throw thrust::system_error(cudaErrorLaunchFailure, thrust::cuda_category(), - message); - } -} - -inline void throw_on_error(cudnnStatus_t stat, const char* message) { - std::stringstream ss; - if (stat == CUDNN_STATUS_SUCCESS) { - return; - } else { - ss << cudnnGetErrorString(stat); - ss << ", " << message; - throw std::runtime_error(ss.str()); - } -} - -inline void throw_on_error(cublasStatus_t stat, const char* message) { - std::stringstream ss; - if (stat == CUBLAS_STATUS_SUCCESS) { - return; - } else if (stat == CUBLAS_STATUS_NOT_INITIALIZED) { - ss << "CUBLAS: not initialized"; - } else if (stat == CUBLAS_STATUS_ALLOC_FAILED) { - ss << "CUBLAS: alloc failed"; - } else if (stat == CUBLAS_STATUS_INVALID_VALUE) { - ss << "CUBLAS: invalid value"; - } else if (stat == CUBLAS_STATUS_ARCH_MISMATCH) { - ss << "CUBLAS: arch mismatch"; - } else if (stat == CUBLAS_STATUS_MAPPING_ERROR) { - ss << "CUBLAS: mapping error"; - } else if (stat == CUBLAS_STATUS_EXECUTION_FAILED) { - ss << "CUBLAS: execution failed"; - } else if (stat == CUBLAS_STATUS_INTERNAL_ERROR) { - ss << "CUBLAS: internal error"; - } else if (stat == CUBLAS_STATUS_NOT_SUPPORTED) { - ss << "CUBLAS: not supported"; - } else if (stat == CUBLAS_STATUS_LICENSE_ERROR) { - ss << "CUBLAS: license error"; - } - ss << ", " << message; - throw std::runtime_error(ss.str()); -} - -inline void throw_on_error(cublasStatus_t stat) { - const char* message = ""; - throw_on_error(stat, message); -} - -#endif // PADDLE_ONLY_CPU - -inline void throw_on_error(int stat, const char* message) { - if (stat) { - throw std::runtime_error(message + (", stat = " + std::to_string(stat))); - } -} - -} // namespace platform -} // namespace paddle diff --git a/paddle/platform/gpu_info.cc b/paddle/platform/gpu_info.cc index a1383d3524..cf9921e870 100644 --- a/paddle/platform/gpu_info.cc +++ b/paddle/platform/gpu_info.cc @@ -14,7 +14,7 @@ limitations under the License. */ #include "paddle/platform/gpu_info.h" #include "gflags/gflags.h" -#include "paddle/platform/error.h" +#include "paddle/platform/enforce.h" DEFINE_double(fraction_of_gpu_memory_to_use, 0.95, "Default use 95% of GPU memory for PaddlePaddle," @@ -25,7 +25,7 @@ namespace platform { int GetDeviceCount() { int count; - throw_on_error( + PADDLE_ENFORCE( cudaGetDeviceCount(&count), "cudaGetDeviceCount failed in paddle::platform::GetDeviceCount"); return count; @@ -33,19 +33,19 @@ int GetDeviceCount() { int GetCurrentDeviceId() { int device_id; - throw_on_error( + PADDLE_ENFORCE( cudaGetDevice(&device_id), "cudaGetDevice failed in paddle::platform::GetCurrentDeviceId"); return device_id; } void SetDeviceId(int id) { - throw_on_error(cudaSetDevice(id), + PADDLE_ENFORCE(cudaSetDevice(id), "cudaSetDevice failed in paddle::platform::SetDeviceId"); } void GpuMemoryUsage(size_t& available, size_t& total) { - throw_on_error(cudaMemGetInfo(&available, &total), + PADDLE_ENFORCE(cudaMemGetInfo(&available, &total), "cudaMemGetInfo failed in paddle::platform::GetMemoryUsage"); } From 2680dca9c8cfc4087bdfd0a402e9b9ec116ea824 Mon Sep 17 00:00:00 2001 From: liaogang Date: Sat, 15 Jul 2017 01:37:02 +0800 Subject: [PATCH 02/24] ENH: add cuda enforce to PADDLE_ENFORCE --- paddle/platform/enforce.h | 160 ++++++++++++++++++++++++++++++++ paddle/platform/enforce_test.cc | 35 +++++++ 2 files changed, 195 insertions(+) create mode 100644 paddle/platform/enforce.h create mode 100644 paddle/platform/enforce_test.cc diff --git a/paddle/platform/enforce.h b/paddle/platform/enforce.h new file mode 100644 index 0000000000..0e40bd798c --- /dev/null +++ b/paddle/platform/enforce.h @@ -0,0 +1,160 @@ +/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#pragma once + +#include +#include +#include +#include + +#ifndef PADDLE_ONLY_CPU + +#include "paddle/platform/dynload/cublas.h" +#include "paddle/platform/dynload/cudnn.h" +#include "paddle/platform/dynload/curand.h" + +#include +#include +#include +#include +#include + +#endif // PADDLE_ONLY_CPU + +namespace paddle { +namespace platform { + +/** + * @brief Enforce exception. Inherits std::exception + * + * All enforce condition not met, will throw an EnforceNotMet exception. + */ +class EnforceNotMet : public std::exception { + public: + EnforceNotMet(const std::string& msg, const char* file, int fileline) { + std::ostringstream sout; + sout << msg << " at [" << file << ":" << fileline << "];"; + all_msg_ = sout.str(); + } + + const char* what() const noexcept override { return all_msg_.c_str(); } + + private: + std::string all_msg_; +}; + +// From https://stackoverflow.com/questions/30130930/ +// __buildin_expect is in C++ 11 standard. Since the condition which enforced +// should be true in most situation, it will make the compiler generate faster +// code by adding `UNLIKELY` macro. +#define UNLIKELY(condition) __builtin_expect(static_cast(condition), 0) + +/** + * @brief Throw a EnforceNotMet exception, automatically filled __FILE__ & + * __LINE__ + * + * This macro take __VA_ARGS__, user can pass any type if that type can + * serialize to std::ostream + */ +#define PADDLE_THROW(...) \ + do { \ + throw ::paddle::platform::EnforceNotMet( \ + ::paddle::string::Sprintf(__VA_ARGS__), __FILE__, __LINE__); \ + } while (0) + +#ifndef PADDLE_ONLY_CPU + +template +inline void throw_on_error(cudaError_t e, const Args&... args) { + if (UNLIKELY(!(e))) { + std::stringstream ss; + ss << ::paddle::string::Sprintf(args...); + ss << ::paddle::string::Sprintf(" at [%s:%s];", __FILE__, __LINE__); + throw thrust::system_error(e, thrust::cuda_category(), ss.str()); + } +} + +template +inline void throw_on_error(curandStatus_t stat, const Args&... args) { + if (stat != CURAND_STATUS_SUCCESS) { + std::stringstream ss; + ss << ::paddle::string::Sprintf(args...); + ss << ::paddle::string::Sprintf(" at [%s:%s];", __FILE__, __LINE__); + throw thrust::system_error(cudaErrorLaunchFailure, thrust::cuda_category(), + ss.str()); + } +} + +template +inline void throw_on_error(cudnnStatus_t stat, const Args&... args) { + if (stat == CUDNN_STATUS_SUCCESS) { + return; + } else { + std::stringstream ss; + ss << ::paddle::platform::dynload::cudnnGetErrorString(stat); + ss << ", " << ::paddle::string::Sprintf(args...); + ss << ::paddle::string::Sprintf(" at [%s:%s];", __FILE__, __LINE__); + throw std::runtime_error(ss.str()); + } +} + +template +inline void throw_on_error(cublasStatus_t stat, const Args&... args) { + std::stringstream ss; + if (stat == CUBLAS_STATUS_SUCCESS) { + return; + } else if (stat == CUBLAS_STATUS_NOT_INITIALIZED) { + ss << "CUBLAS: not initialized"; + } else if (stat == CUBLAS_STATUS_ALLOC_FAILED) { + ss << "CUBLAS: alloc failed"; + } else if (stat == CUBLAS_STATUS_INVALID_VALUE) { + ss << "CUBLAS: invalid value"; + } else if (stat == CUBLAS_STATUS_ARCH_MISMATCH) { + ss << "CUBLAS: arch mismatch"; + } else if (stat == CUBLAS_STATUS_MAPPING_ERROR) { + ss << "CUBLAS: mapping error"; + } else if (stat == CUBLAS_STATUS_EXECUTION_FAILED) { + ss << "CUBLAS: execution failed"; + } else if (stat == CUBLAS_STATUS_INTERNAL_ERROR) { + ss << "CUBLAS: internal error"; + } else if (stat == CUBLAS_STATUS_NOT_SUPPORTED) { + ss << "CUBLAS: not supported"; + } else if (stat == CUBLAS_STATUS_LICENSE_ERROR) { + ss << "CUBLAS: license error"; + } + ss << ", " << ::paddle::string::Sprintf(args...); + ss << ::paddle::string::Sprintf(" at [%s:%s];", __FILE__, __LINE__); + throw std::runtime_error(ss.str()); +} + +#endif // PADDLE_ONLY_CPU + +template +inline void throw_on_error(int stat, const Args&... args) { + if (UNLIKELY(!(stat))) { + PADDLE_THROW(args...); + } +} + +/** + * @brief Enforce a condition, otherwise throw an EnforceNotMet + */ +#define PADDLE_ENFORCE(condition, ...) \ + do { \ + ::paddle::platform::throw_on_error(condition, __VA_ARGS__); \ + } while (0) + +} // namespace platform +} // namespace paddle diff --git a/paddle/platform/enforce_test.cc b/paddle/platform/enforce_test.cc new file mode 100644 index 0000000000..2d96b51ab0 --- /dev/null +++ b/paddle/platform/enforce_test.cc @@ -0,0 +1,35 @@ +/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#include +#include + +TEST(ENFORCE, OK) { + PADDLE_ENFORCE(true, "Enforce is ok %d now %f", 123, 0.345); + size_t val = 1; + const size_t limit = 10; + PADDLE_ENFORCE(val < limit, "Enforce is OK too"); +} + +TEST(ENFORCE, FAILED) { + bool in_catch = false; + try { + PADDLE_ENFORCE(false, "Enforce is not ok %d at all", 123); + } catch (paddle::platform::EnforceNotMet err) { + in_catch = true; + std::string msg = "Enforce is not ok 123 at all"; + const char* what = err.what(); + for (size_t i = 0; i < msg.length(); ++i) { + ASSERT_EQ(what[i], msg[i]); + } + } + ASSERT_TRUE(in_catch); +} From 90c4cd8323ab7dc375e70ce9e84949854f58ec80 Mon Sep 17 00:00:00 2001 From: liaogang Date: Sat, 15 Jul 2017 08:29:55 +0800 Subject: [PATCH 03/24] FIX: header file --- paddle/framework/tensor.h | 2 +- paddle/platform/device_context.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/paddle/framework/tensor.h b/paddle/framework/tensor.h index 5fdbb4f07a..c6b9c00554 100644 --- a/paddle/framework/tensor.h +++ b/paddle/framework/tensor.h @@ -18,8 +18,8 @@ limitations under the License. */ #include #include #include "paddle/framework/ddim.h" -#include "paddle/platform/enforce.h" #include "paddle/memory/memory.h" +#include "paddle/platform/enforce.h" #include "paddle/platform/place.h" namespace paddle { diff --git a/paddle/platform/device_context.h b/paddle/platform/device_context.h index d2569fdc91..2dded7d79e 100644 --- a/paddle/platform/device_context.h +++ b/paddle/platform/device_context.h @@ -12,15 +12,16 @@ limitations under the License. */ #pragma once #include "paddle/platform/enforce.h" +#include "paddle/platform/place.h" + #ifndef PADDLE_ONLY_CPU #include "paddle/platform/dynload/cublas.h" #include "paddle/platform/dynload/cudnn.h" #include "paddle/platform/dynload/curand.h" -#include "paddle/platform/error.h" #include "paddle/platform/gpu_info.h" #define EIGEN_USE_GPU #endif -#include + #include #include From 7010a5da1a0d91da41fddd4799eff157efa19014 Mon Sep 17 00:00:00 2001 From: liaogang Date: Sat, 15 Jul 2017 10:09:08 +0800 Subject: [PATCH 04/24] FIX: throw_on_error on cuda --- paddle/platform/enforce.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paddle/platform/enforce.h b/paddle/platform/enforce.h index 0e40bd798c..9431204a68 100644 --- a/paddle/platform/enforce.h +++ b/paddle/platform/enforce.h @@ -78,7 +78,7 @@ class EnforceNotMet : public std::exception { template inline void throw_on_error(cudaError_t e, const Args&... args) { - if (UNLIKELY(!(e))) { + if (e) { std::stringstream ss; ss << ::paddle::string::Sprintf(args...); ss << ::paddle::string::Sprintf(" at [%s:%s];", __FILE__, __LINE__); From d3373c5b853d0570842fbadedb1d969b94cef1bc Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 18 Jul 2017 18:55:29 +0800 Subject: [PATCH 05/24] Skeleton Of fully connected operator * Fc operator is a grouped operator, which combined by may internal operators. * InferShape & Run a FC operator in Python. --- paddle/framework/attr_checker.h | 35 +++++++++ paddle/framework/net.cc | 6 +- paddle/framework/net.h | 5 +- paddle/operators/CMakeLists.txt | 6 +- paddle/operators/fc_op.cc | 76 +++++++++++++++++++ paddle/pybind/CMakeLists.txt | 2 +- paddle/pybind/pybind.cc | 46 ++++++----- .../paddle/v2/framework/tests/CMakeLists.txt | 2 +- .../paddle/v2/framework/tests/test_fc_op.py | 43 +++++++++++ 9 files changed, 195 insertions(+), 26 deletions(-) create mode 100644 paddle/operators/fc_op.cc create mode 100644 python/paddle/v2/framework/tests/test_fc_op.py diff --git a/paddle/framework/attr_checker.h b/paddle/framework/attr_checker.h index c0c33d8114..f2d88f3cb0 100644 --- a/paddle/framework/attr_checker.h +++ b/paddle/framework/attr_checker.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "paddle/framework/enforce.h" @@ -41,6 +42,35 @@ class DefaultValueSetter { T default_value_; }; +template +class EnumInContainer { + public: + explicit EnumInContainer(const std::unordered_set& c) : container_(c) {} + void operator()(T& val) const { + PADDLE_ENFORCE(container_.find(val) != container_.end(), + "Value %s is not in enum container %s", val, + ContainerDebugString()); + } + + private: + std::string ContainerDebugString() const { + std::ostringstream sout; + sout << "["; + size_t cnt = 0; + for (auto& v : container_) { + sout << v; + ++cnt; + if (cnt != container_.size()) { + sout << " ,"; + } + } + sout << "]"; + return sout.str(); + } + + std::unordered_set container_; +}; + // check whether a certain attribute fit its limits // an attribute can have more than one limits template @@ -50,6 +80,11 @@ class TypedAttrChecker { public: TypedAttrChecker(const std::string& attr_name) : attr_name_(attr_name) {} + TypedAttrChecker& InEnum(const std::unordered_set& range) { + value_checkers_.push_back(EnumInContainer(range)); + return *this; + } + TypedAttrChecker& LargerThan(const T& lower_bound) { value_checkers_.push_back(LargerThanChecker(lower_bound)); return *this; diff --git a/paddle/framework/net.cc b/paddle/framework/net.cc index b9cd732d40..501536657d 100644 --- a/paddle/framework/net.cc +++ b/paddle/framework/net.cc @@ -19,7 +19,10 @@ namespace paddle { namespace framework { -void PlainNet::CompleteAddOp() { +void PlainNet::CompleteAddOp(bool calc) { + add_op_done_ = true; + if (!calc) return; + std::unordered_set input_set; std::unordered_set output_set; std::unordered_set temp_output; @@ -52,7 +55,6 @@ void PlainNet::CompleteAddOp() { } attrs_["temporary_index"] = tmp_index; - add_op_done_ = true; } std::string PlainNet::DebugString() const { diff --git a/paddle/framework/net.h b/paddle/framework/net.h index 33bb30ea07..19c5fa223b 100644 --- a/paddle/framework/net.h +++ b/paddle/framework/net.h @@ -16,7 +16,6 @@ limitations under the License. */ #include #include -#include "paddle/framework/net_proto.pb.h" #include "paddle/framework/op_proto.pb.h" #include "paddle/framework/op_registry.h" #include "paddle/framework/scope.h" @@ -41,7 +40,7 @@ namespace framework { class Net : public OperatorBase { public: virtual void AddOp(const OperatorPtr& op) = 0; - virtual void CompleteAddOp() = 0; + virtual void CompleteAddOp(bool calc) = 0; }; using NetPtr = std::shared_ptr; @@ -86,7 +85,7 @@ class PlainNet : public Net { ops_.push_back(op); } - void CompleteAddOp() override; + void CompleteAddOp(bool calculate = true) override; std::string DebugString() const override; diff --git a/paddle/operators/CMakeLists.txt b/paddle/operators/CMakeLists.txt index f47c3a4208..bc64bfd7ec 100644 --- a/paddle/operators/CMakeLists.txt +++ b/paddle/operators/CMakeLists.txt @@ -27,7 +27,8 @@ function(op_library TARGET) endif() list(LENGTH cu_srcs cu_srcs_len) - if (${cu_srcs_len} EQUAL 0) + list(LENGTH op_library_DEPS dep_len) + if (${cu_srcs_len} EQUAL 0 AND ${dep_len} EQUAL 0) message(WARNING "The op library ${TARGET} not support GPU!") endif() @@ -47,3 +48,6 @@ op_library(mul_op SRCS mul_op.cc mul_op.cu) op_library(rowwise_add_op SRCS rowwise_add_op.cu rowwise_add_op.cc) op_library(sigmoid_op SRCS sigmoid_op.cu sigmoid_op.cc) op_library(softmax_op SRCS softmax_op.cc softmax_op.cu) + +op_library(fc_op SRCS fc_op.cc DEPS mul_op rowwise_add_op sigmoid_op + softmax_op net) diff --git a/paddle/operators/fc_op.cc b/paddle/operators/fc_op.cc new file mode 100644 index 0000000000..01e96f4c48 --- /dev/null +++ b/paddle/operators/fc_op.cc @@ -0,0 +1,76 @@ +/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ + +#include "paddle/framework/net.h" +#include "paddle/framework/op_registry.h" +#include "paddle/framework/operator.h" + +namespace paddle { +namespace operators { + +class FullyConnectedOp : public framework::PlainNet { +public: + void Init() override { + AddOp(framework::OpRegistry::CreateOp("mul", + { + Input("X"), Input("W"), + }, + {Output("before_act")}, + {})); + auto b = Input("b"); + if (b != framework::OperatorBase::EMPTY_VAR_NAME()) { + AddOp(framework::OpRegistry::CreateOp("rowwise_add", + {Output("before_act"), Input("b")}, + {Output("before_act")}, + {})); + } + + auto activation = GetAttr("activation"); + AddOp(framework::OpRegistry::CreateOp( + activation, {Output("before_act")}, {Output("Y")}, {})); + CompleteAddOp(false); + } +}; + +class FullyConnectedOpMaker : public framework::OpProtoAndCheckerMaker { +public: + FullyConnectedOpMaker(framework::OpProto *proto, + framework::OpAttrChecker *op_checker) + : OpProtoAndCheckerMaker(proto, op_checker) { + AddInput("X", "the input of fc operator"); + AddInput("W", "the weight of fc operator"); + AddInput("b", "the bias of fc operator"); + + AddOutput("Y", "the output of fc operator"); + AddOutput( + "before_act", "the before activation output of fc operator", true); + AddAttr("activation", "The activation key for fc layer") + .SetDefault("sigmoid") + .InEnum({"sigmoid", "softmax"}); + + //! TODO(yuyang18): Complete comment; + AddComment("FullyConnected Operator"); + } +}; +} // namespace operators +} // namespace paddle + +USE_OP(mul); +USE_OP(rowwise_add); +USE_OP(sigmoid); +USE_OP(softmax); + +REGISTER_OP(fc, + paddle::operators::FullyConnectedOp, + paddle::operators::FullyConnectedOpMaker); diff --git a/paddle/pybind/CMakeLists.txt b/paddle/pybind/CMakeLists.txt index 00b14a9432..29fb29c7c1 100644 --- a/paddle/pybind/CMakeLists.txt +++ b/paddle/pybind/CMakeLists.txt @@ -1,2 +1,2 @@ cc_library(paddle_pybind SHARED SRCS pybind.cc DEPS pybind python - add_op mul_op rowwise_add_op sigmoid_op softmax_op) + add_op fc_op) diff --git a/paddle/pybind/pybind.cc b/paddle/pybind/pybind.cc index fc9c6544c3..e0f4c02459 100644 --- a/paddle/pybind/pybind.cc +++ b/paddle/pybind/pybind.cc @@ -14,6 +14,7 @@ limitations under the License. */ #include #include +#include #include #include #include @@ -26,10 +27,7 @@ namespace py = pybind11; namespace pd = paddle::framework; USE_OP(add_two); -USE_OP(softmax); -USE_OP(mul); -USE_OP(rowwise_add); -USE_OP(sigmoid); +USE_OP_WITHOUT_KERNEL(fc); PYBIND11_PLUGIN(core) { py::module m("core", "C++ core of Paddle Paddle"); @@ -53,7 +51,9 @@ PYBIND11_PLUGIN(core) { self.mutable_data(paddle::platform::CPUPlace()); }) .def("set", paddle::pybind::PyTensorSetFromArray) - .def("set", paddle::pybind::PyTensorSetFromArray); + .def("set", paddle::pybind::PyTensorSetFromArray) + .def("shape", + [](pd::Tensor& self) { return pd::vectorize(self.dims()); }); py::class_(m, "Variable", R"DOC(Variable Class. @@ -83,15 +83,16 @@ All parameter, weight, gradient are variables in Paddle. //! @note: Be careful! PyBind will return std::string as an unicode, not //! Python str. If you want a str object, you should cast them in Python. - m.def("get_all_op_protos", []() -> std::vector { + m.def("get_all_op_protos", []() -> std::vector { auto& protos = pd::OpRegistry::protos(); - std::vector ret_values; + std::vector ret_values; for (auto it = protos.begin(); it != protos.end(); ++it) { PADDLE_ENFORCE(it->second.IsInitialized(), "OpProto must all be initialized"); - ret_values.emplace_back(); - PADDLE_ENFORCE(it->second.SerializeToString(&ret_values.back()), + std::string str; + PADDLE_ENFORCE(it->second.SerializeToString(&str), "Serialize OpProto Error. This could be a bug of Paddle."); + ret_values.push_back(py::bytes(str)); } return ret_values; }); @@ -101,17 +102,26 @@ All parameter, weight, gradient are variables in Paddle. .def("empty", pd::OperatorBase::EMPTY_VAR_NAME) .def("temp", pd::OperatorBase::TMP_VAR_NAME); + py::class_(m, "DeviceContext") + .def_static("cpu_context", []() -> paddle::platform::DeviceContext* { + return new paddle::platform::CPUDeviceContext(); + }); + py::class_(m, "Operator") .def("__str__", &pd::OperatorBase::DebugString) - .def_static("create", [](const std::string& protobin) { - pd::OpDesc desc; - PADDLE_ENFORCE(desc.ParsePartialFromString(protobin), - "Cannot parse user input to OpDesc"); - PADDLE_ENFORCE(desc.IsInitialized(), - "User OpDesc is not initialized, reason %s", - desc.InitializationErrorString()); - return pd::OpRegistry::CreateOp(desc); - }); + .def_static("create", + [](const std::string& protobin) { + pd::OpDesc desc; + PADDLE_ENFORCE(desc.ParsePartialFromString(protobin), + "Cannot parse user input to OpDesc"); + PADDLE_ENFORCE(desc.IsInitialized(), + "User OpDesc is not initialized, reason %s", + desc.InitializationErrorString()); + return pd::OpRegistry::CreateOp(desc); + }) + .def("infer_shape", &pd::OperatorBase::InferShape) + .def("run", &pd::OperatorBase::Run) + .def("outputs", [](const pd::OperatorPtr& op) { return op->outputs_; }); return m.ptr(); } diff --git a/python/paddle/v2/framework/tests/CMakeLists.txt b/python/paddle/v2/framework/tests/CMakeLists.txt index 4ce2bef6fc..b75b7442d1 100644 --- a/python/paddle/v2/framework/tests/CMakeLists.txt +++ b/python/paddle/v2/framework/tests/CMakeLists.txt @@ -1,3 +1,3 @@ add_python_test(test_framework test_protobuf.py test_scope.py test_default_scope_funcs.py test_op_creation_methods.py - test_tensor.py) + test_tensor.py test_fc_op.py) diff --git a/python/paddle/v2/framework/tests/test_fc_op.py b/python/paddle/v2/framework/tests/test_fc_op.py new file mode 100644 index 0000000000..59e7e61249 --- /dev/null +++ b/python/paddle/v2/framework/tests/test_fc_op.py @@ -0,0 +1,43 @@ +import paddle.v2.framework.core as core +import unittest +import numpy +import paddle.v2.framework.create_op_creation_methods as creation + + +class TestFc(unittest.TestCase): + def test_fc(self): + scope = core.Scope(None) + x = scope.create_var("X") + x_tensor = x.get_tensor() + x_tensor.set_dims([1000, 784]) + x_tensor.alloc_float() + + w = scope.create_var("W") + w_tensor = w.get_tensor() + w_tensor.set_dims([784, 100]) + w_tensor.alloc_float() + + w_tensor.set(numpy.random.random((784, 100)).astype("float32")) + + # Set a real numpy array here. + # x_tensor.set(numpy.array([])) + + op = creation.op_creations.fc(X="X", Y="Y", W="W") + + for out in op.outputs(): + if scope.get_var(out) is None: + scope.create_var(out).get_tensor() + + tensor = scope.get_var("Y").get_tensor() + op.infer_shape(scope) + self.assertEqual([1000, 100], tensor.shape()) + + ctx = core.DeviceContext.cpu_context() + + op.run(scope, ctx) + + # After complete all ops, check Y is expect or not. + + +if __name__ == '__main__': + unittest.main() From 3402b6ad39c5ac8ba40a6981e206e554490217ff Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 18 Jul 2017 20:35:34 +0800 Subject: [PATCH 06/24] Add Unittest of add_two_op --- .../framework/create_op_creation_methods.py | 4 ++ .../paddle/v2/framework/tests/CMakeLists.txt | 2 +- .../paddle/v2/framework/tests/op_test_util.py | 50 +++++++++++++++++++ .../v2/framework/tests/test_add_two_op.py | 17 +++++++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 python/paddle/v2/framework/tests/op_test_util.py create mode 100644 python/paddle/v2/framework/tests/test_add_two_op.py diff --git a/python/paddle/v2/framework/create_op_creation_methods.py b/python/paddle/v2/framework/create_op_creation_methods.py index c2a7ae7692..7248c3f52a 100644 --- a/python/paddle/v2/framework/create_op_creation_methods.py +++ b/python/paddle/v2/framework/create_op_creation_methods.py @@ -217,6 +217,10 @@ def create_op_creation_method(op_proto): return core.Operator.create(opdesc.SerializeToString()) __impl__.__doc__ = get_docstring_from_op_proto(op_proto) + __impl__.all_input_args = [var.name for var in op_proto.inputs] + __impl__.all_output_args = [var.name for var in op_proto.outputs] + __impl__.all_attr_args = [attr.name for attr in op_proto.attrs] + return __impl__ diff --git a/python/paddle/v2/framework/tests/CMakeLists.txt b/python/paddle/v2/framework/tests/CMakeLists.txt index b75b7442d1..f71009aa85 100644 --- a/python/paddle/v2/framework/tests/CMakeLists.txt +++ b/python/paddle/v2/framework/tests/CMakeLists.txt @@ -1,3 +1,3 @@ add_python_test(test_framework test_protobuf.py test_scope.py test_default_scope_funcs.py test_op_creation_methods.py - test_tensor.py test_fc_op.py) + test_tensor.py test_fc_op.py test_add_two_op.py) diff --git a/python/paddle/v2/framework/tests/op_test_util.py b/python/paddle/v2/framework/tests/op_test_util.py new file mode 100644 index 0000000000..237f9b7eb0 --- /dev/null +++ b/python/paddle/v2/framework/tests/op_test_util.py @@ -0,0 +1,50 @@ +import paddle.v2.framework.core as core +import unittest +import numpy +import paddle.v2.framework.create_op_creation_methods as creation + + +class OpTestMeta(type): + def __new__(cls, name, bases, attrs): + obj = super(OpTestMeta, cls).__new__(cls, name, bases, attrs) + + def test_all(self): + func = getattr(creation.op_creations, self.type, None) + self.assertIsNotNone(func) + + scope = core.Scope(None) + kwargs = dict() + + for in_name in func.all_input_args: + if hasattr(self, in_name): + kwargs[in_name] = in_name + var = scope.create_var(in_name).get_tensor() + arr = getattr(self, in_name) + var.set_dims(arr.shape) + var.set(arr) + else: + kwargs[in_name] = "@EMPTY@" + + for out_name in func.all_output_args: + if hasattr(self, out_name): + kwargs[out_name] = out_name + scope.create_var(out_name).get_tensor() + + for attr_name in func.all_attr_args: + if hasattr(self, attr_name): + kwargs[attr_name] = getattr(self, attr_name) + + op = func(**kwargs) + + op.infer_shape(scope) + + ctx = core.DeviceContext.cpu_context() + op.run(scope, ctx) + + for out_name in func.all_output_args: + actual = numpy.array(scope.get_var(out_name).get_tensor()) + expect = getattr(self, out_name) + numpy.testing.assert_almost_equal(actual, expect) + + obj.test_all = test_all + return obj diff --git a/python/paddle/v2/framework/tests/test_add_two_op.py b/python/paddle/v2/framework/tests/test_add_two_op.py new file mode 100644 index 0000000000..a06d7a78ec --- /dev/null +++ b/python/paddle/v2/framework/tests/test_add_two_op.py @@ -0,0 +1,17 @@ +import unittest +from op_test_util import OpTestMeta +import numpy + + +class TestAddOp(unittest.TestCase): + __metaclass__ = OpTestMeta + + def setUp(self): + self.type = "add_two" + self.X = numpy.random.random((342, 345)).astype("float32") + self.Y = numpy.random.random((342, 345)).astype("float32") + self.Out = self.X + self.Y + + +if __name__ == '__main__': + unittest.main() From 642d3c4687eb91c3a7fd026e3d8ae15957c8836d Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Tue, 18 Jul 2017 15:05:33 -0700 Subject: [PATCH 07/24] Refactorize Tensor to Eigen convesion --- paddle/framework/ddim.h | 11 ---- paddle/framework/eigen.h | 103 ++++++++++++++++++++++++++++++++ paddle/framework/tensor.h | 60 ------------------- paddle/framework/tensor_types.h | 67 --------------------- 4 files changed, 103 insertions(+), 138 deletions(-) create mode 100644 paddle/framework/eigen.h delete mode 100644 paddle/framework/tensor_types.h diff --git a/paddle/framework/ddim.h b/paddle/framework/ddim.h index 070850375d..06c4c583b3 100644 --- a/paddle/framework/ddim.h +++ b/paddle/framework/ddim.h @@ -119,17 +119,6 @@ int arity(const DDim& ddim); std::ostream& operator<<(std::ostream&, const DDim&); -template -Eigen::DSizes ToEigenDSizes(const DDim& dims) { - int rank = arity(dims); - PADDLE_ENFORCE(rank == NDIMS, "DDim and NDIMS must be same"); - Eigen::DSizes dsizes; - for (int d = 0; d < rank; d++) { - dsizes[d] = dims[d]; - } - return dsizes; -} - } // namespace framework } // namespace paddle diff --git a/paddle/framework/eigen.h b/paddle/framework/eigen.h new file mode 100644 index 0000000000..edbbc2694a --- /dev/null +++ b/paddle/framework/eigen.h @@ -0,0 +1,103 @@ +/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#pragma once + +#include "paddle/platform/tensor.h" +#include "unsupported/Eigen/CXX11/Tensor" + +namespace paddle { +namespace framework { + +// EigenDim converts paddle::platform::DDim into Eigen::DSizes. +template +struct EigenDim { + typedef Eigen::DSizes Type; + + static Type From(const DDim& dims) { + PADDLE_ENFORCE(arity(dims) == D, "D must match arity(DDim)"); + Type ret; + for (int d = 0; d < rank; d++) { + ret[d] = dims[d]; + } + return ret; + } +}; + +// Interpret paddle::platform::Tensor as EigenTensor and EigenConstTensor. +template +struct EigenTensor { + using Type = Eigen::TensorMap, + Eigen::Aligned>; + + using ConstType = + Eigen::TensorMap, + Eigen::Aligned> + ConstTensor; + + static Type From(Tensor& tensor, DDim dims) { + return Type(tensor.data(), EigenDim::From(dims)); + } + + static Type From(Tensor& tensor) { return From(tensor, tensor.dims_); } + + static ConstType From(const Tensor& tensor, DDim dims) { + return ConstType(tensor.data(), EigenDim::From(dims)); + } + + static ConstType From(const Tensor& tensor) { + return From(tensor, tensor.dims_); + } +}; + +// Interpret paddle::platform::Tensor as EigenVecotr and EigenConstVector. +template +struct EigenVector { + using EigenVector = + Eigen::TensorMap, + Eigen::Aligned>; + + using EigenConstVector = + Eigen::TensorMap, + Eigen::Aligned>; + + static Type From(Tensor& tensor) { return EigenTensor::From(tensor); } + + static ConstType From(const Tensor& tensor) { + return EigenTensor::From(tensor); + } +}; + +// Interpret paddle::platform::Tensor as EigenMatrix and EigenConstMatrix. +template +struct EigenMatrix { + template + using EigenMatrix = + Eigen::TensorMap, + Eigen::Aligned>; + + template + using EigenConstMatrix = + Eigen::TensorMap, + Eigen::Aligned>; + + static Type From(Tensor& tensor) { return EigenTensor::From(tensor); } + + static ConstType From(const Tensor& tensor) { + return EigenTensor::From(tensor); + } +}; + +} // namespace framework +} // namespace paddle diff --git a/paddle/framework/tensor.h b/paddle/framework/tensor.h index 4f07350e59..1235b53227 100644 --- a/paddle/framework/tensor.h +++ b/paddle/framework/tensor.h @@ -86,66 +86,6 @@ class Tensor { offset_); } - template - typename TTypes::Tensor shaped(DDim new_dims) { - Eigen::array dims = - paddle::framework::ToEigenDSizes(new_dims); - return typename TTypes::Tensor(raw_data(), dims); - } - - template - typename TTypes::Tensor tensor() { - return typename TTypes::Tensor( - raw_data(), paddle::framework::ToEigenDSizes(dims_)); - } - - // flat to rank = 1 - template - typename TTypes::Flat flat() { - return shaped(make_ddim({static_cast(product(dims_))})); - } - - // to TensorType Vec - template - typename TTypes::Vec vec() { - return tensor(); - } - - // to TensorType Matrix - template - typename TTypes::Matrix matrix() { - return tensor(); - } - - // const versions of all the methods above. - template - typename TTypes::Tensor shaped(DDim new_dims) const { - Eigen::array dims = - paddle::framework::ToEigenDSizes(new_dims); - return typename TTypes::Tensor(data(), dims); - } - - template - typename TTypes::ConstantTensor tensor() const { - return typename TTypes::Tensor( - data(), paddle::framework::ToEigenDSizes(dims_)); - } - - template - typename TTypes::ConstFlat flat() const { - return shaped(make_ddim({static_cast(product(dims_))})); - } - - template - typename TTypes::ConstVec vec() const { - return tensor(); - } - - template - typename TTypes::ConstMatrix matrix() const { - return tensor(); - } - template void ShareDataFrom(const Tensor& src) { src.CheckDims(); diff --git a/paddle/framework/tensor_types.h b/paddle/framework/tensor_types.h deleted file mode 100644 index 4bf27a377e..0000000000 --- a/paddle/framework/tensor_types.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. */ - -#pragma once - -#include "unsupported/Eigen/CXX11/Tensor" - -namespace paddle { -namespace framework { - -// Helper to define Tensor types given that the scalar is of type T. -template -struct TTypes { - // Rank- tensor of scalar type T. - typedef Eigen::TensorMap, - Eigen::Aligned> - Tensor; - typedef Eigen::TensorMap< - Eigen::Tensor, Eigen::Aligned> - ConstTensor; - - // Scalar tensor (implemented as a rank-0 tensor) of scalar type T. - typedef Eigen::TensorMap< - Eigen::TensorFixedSize, Eigen::RowMajor, IndexType>, - Eigen::Aligned> - Scalar; - typedef Eigen::TensorMap, - Eigen::RowMajor, IndexType>, - Eigen::Aligned> - ConstScalar; - - // Rank-1 tensor (vector) of scalar type T. - typedef Eigen::TensorMap, - Eigen::Aligned> - Flat; - typedef Eigen::TensorMap< - Eigen::Tensor, Eigen::Aligned> - ConstFlat; - typedef Eigen::TensorMap, - Eigen::Aligned> - Vec; - typedef Eigen::TensorMap< - Eigen::Tensor, Eigen::Aligned> - ConstVec; - - // Rank-2 tensor (matrix) of scalar type T. - typedef Eigen::TensorMap, - Eigen::Aligned> - Matrix; - typedef Eigen::TensorMap< - Eigen::Tensor, Eigen::Aligned> - ConstMatrix; -}; - -} // namespace framework -} // namespace paddle From cb1d1f167c95b0c7ded6cb2c68d65de35765c6a5 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Tue, 18 Jul 2017 15:35:51 -0700 Subject: [PATCH 08/24] Add unit test --- paddle/framework/eigen_test.cc | 37 ++++++++++++++++++++++++++++++++++ paddle/framework/tensor.h | 15 +++++++++++--- 2 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 paddle/framework/eigen_test.cc diff --git a/paddle/framework/eigen_test.cc b/paddle/framework/eigen_test.cc new file mode 100644 index 0000000000..c5f27a3298 --- /dev/null +++ b/paddle/framework/eigen_test.cc @@ -0,0 +1,37 @@ +/* + Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "paddle/framework/eigen.h" + +#include + +#include "paddle/framework/tensor.h" + +TEST(Eigen, Tensor) { + using paddle::platform::Tensor; + using paddle::platform::EigenTensor; + using paddle::platform::make_ddim; + + Tensor t; + float* p = t.mutable_data(make_ddim({1, 2, 3}), CPUPlace()); + for (int i = 0; i < 1 * 2 * 3; i++) { + p[i] = static_cast(i); + } + + EigenTensor::Type et = EigenTensor::From(t); + // TODO: check the content of et. +} + +TEST(Eigen, Vector) {} + +TEST(Eigen, Matrix) {} diff --git a/paddle/framework/tensor.h b/paddle/framework/tensor.h index 1235b53227..405393fb11 100644 --- a/paddle/framework/tensor.h +++ b/paddle/framework/tensor.h @@ -20,7 +20,6 @@ limitations under the License. */ #include #include "paddle/framework/ddim.h" #include "paddle/framework/enforce.h" -#include "paddle/framework/tensor_types.h" #include "paddle/memory/memory.h" #include "paddle/platform/place.h" #include "unsupported/Eigen/CXX11/Tensor" @@ -35,6 +34,18 @@ struct CastToPyBufferImpl; namespace framework { class Tensor { + template + friend struct paddle::pybind::details::CastToPyBufferImpl; + + template + friend struct EigenTensor; + + template + friend struct EigenVector; + + template + friend struct EigenMatrix; + public: Tensor() : offset_(0) {} @@ -191,8 +202,6 @@ class Tensor { std::shared_ptr holder_; // holds the memory block if allocated. DDim dims_; size_t offset_; // marks the begin of tensor data area. - template - friend struct paddle::pybind::details::CastToPyBufferImpl; }; } // namespace framework From 00ed56430782f953ab42e549fe94938271f9e194 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Tue, 18 Jul 2017 16:40:22 -0700 Subject: [PATCH 09/24] Update --- paddle/framework/CMakeLists.txt | 3 +++ paddle/operators/add_op.h | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/paddle/framework/CMakeLists.txt b/paddle/framework/CMakeLists.txt index eb34164623..a00b9c8190 100644 --- a/paddle/framework/CMakeLists.txt +++ b/paddle/framework/CMakeLists.txt @@ -4,8 +4,11 @@ cc_test(enforce_test SRCS enforce_test.cc DEPS enforce) cc_library(ddim SRCS ddim.cc DEPS eigen3) cc_test(ddim_test SRCS ddim_test.cc DEPS ddim) nv_test(dim_test SRCS dim_test.cu DEPS ddim) + cc_library(tensor SRCS tensor.cc DEPS ddim place enforce paddle_memory) cc_test(tensor_test SRCS tensor_test.cc DEPS tensor) +cc_test(eigen_test SRCS eigen_test.cc DEPS tensor) + cc_test(variable_test SRCS variable_test.cc) cc_test(scope_test SRCS scope_test.cc) proto_library(attr_type SRCS attr_type.proto) diff --git a/paddle/operators/add_op.h b/paddle/operators/add_op.h index e08b3fb187..e7c106a23f 100644 --- a/paddle/operators/add_op.h +++ b/paddle/operators/add_op.h @@ -14,6 +14,7 @@ limitations under the License. */ #pragma once #include "glog/logging.h" +#include "paddle/framework/eigen.h" #include "paddle/framework/operator.h" namespace paddle { @@ -29,8 +30,9 @@ public: output->mutable_data(context.GetPlace()); - output->flat().device(*(context.GetEigenDevice())) = - input0.flat() + input1.flat(); + framework::EigenVector::From(*output).device( + *(context.GetEigenDevice())) = + framework::EigenVector(*input0) + framework::EigenVector(*input1); } }; From 2538e20787bf8e652a0acaf129fa73ce06abf20b Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Tue, 18 Jul 2017 16:42:59 -0700 Subject: [PATCH 10/24] Fix wrong inclusion path --- paddle/framework/eigen.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paddle/framework/eigen.h b/paddle/framework/eigen.h index edbbc2694a..28641a389f 100644 --- a/paddle/framework/eigen.h +++ b/paddle/framework/eigen.h @@ -14,7 +14,7 @@ limitations under the License. */ #pragma once -#include "paddle/platform/tensor.h" +#include "paddle/framework/tensor.h" #include "unsupported/Eigen/CXX11/Tensor" namespace paddle { From 3d4e808ce418dc95c3391eaabe24b2d9f4d0e33d Mon Sep 17 00:00:00 2001 From: Helin Wang Date: Wed, 19 Jul 2017 01:05:59 +0000 Subject: [PATCH 11/24] cmake: fix problem that go_library is never rebuilt. `merge_static_libs` also have the similar logic of using ${dummyfile}, I am not sure if there needs a change or not. --- cmake/generic.cmake | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/cmake/generic.cmake b/cmake/generic.cmake index e42e75c12a..534be0abe2 100644 --- a/cmake/generic.cmake +++ b/cmake/generic.cmake @@ -290,8 +290,22 @@ function(go_library TARGET_NAME) set(${TARGET_NAME}_LIB_NAME "${CMAKE_STATIC_LIBRARY_PREFIX}${TARGET_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}" CACHE STRING "output library name for target ${TARGET_NAME}") endif() - # Add dummy code to support `make target_name` under Terminal Command set(dummyfile ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}_dummy.c) + + # This custom command will always run since it depends on a not + # existing file. + add_custom_command( + OUTPUT dummy_rebulid_${TARGET_NAME} + COMMAND cmake -E touch ${dummyfile} + ) + # Create a custom target that depends on the custom command output + # file, so the custom command can be referenced as a dependency by + # `add_dependencies`. + add_custom_target(rebuild_${TARGET_NAME} + DEPENDS dummy_rebulid_${TARGET_NAME} + ) + + # Add dummy code to support `make target_name` under Terminal Command file(WRITE ${dummyfile} "const char * dummy = \"${dummyfile}\";") if (go_library_SHARED OR go_library_shared) add_library(${TARGET_NAME} SHARED ${dummyfile}) @@ -302,6 +316,12 @@ function(go_library TARGET_NAME) add_dependencies(${TARGET_NAME} ${go_library_DEPS}) endif(go_library_DEPS) + # The "source file" of the library is `${dummyfile}` which never + # change, so the target will never rebuild. Make the target depends + # on the custom command that touches the library "source file", so + # rebuild will always happen. + add_dependencies(${TARGET_NAME} rebuild_${TARGET_NAME}) + set(${TARGET_NAME}_LIB_PATH "${CMAKE_CURRENT_BINARY_DIR}/${${TARGET_NAME}_LIB_NAME}" CACHE STRING "output library path for target ${TARGET_NAME}") file(GLOB GO_SOURCE RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.go") From 1981eaf922f3636a9f49209757d52c527d2dbe96 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Tue, 18 Jul 2017 18:37:29 -0700 Subject: [PATCH 12/24] Fix Tensor::data interface --- paddle/framework/eigen.h | 21 ++++++++------------- paddle/framework/eigen_test.cc | 22 ++++++++++++++-------- paddle/framework/tensor.h | 8 ++++---- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/paddle/framework/eigen.h b/paddle/framework/eigen.h index 28641a389f..cd87b042df 100644 --- a/paddle/framework/eigen.h +++ b/paddle/framework/eigen.h @@ -28,7 +28,7 @@ struct EigenDim { static Type From(const DDim& dims) { PADDLE_ENFORCE(arity(dims) == D, "D must match arity(DDim)"); Type ret; - for (int d = 0; d < rank; d++) { + for (int d = 0; d < arity(dims); d++) { ret[d] = dims[d]; } return ret; @@ -43,8 +43,7 @@ struct EigenTensor { using ConstType = Eigen::TensorMap, - Eigen::Aligned> - ConstTensor; + Eigen::Aligned>; static Type From(Tensor& tensor, DDim dims) { return Type(tensor.data(), EigenDim::From(dims)); @@ -64,11 +63,10 @@ struct EigenTensor { // Interpret paddle::platform::Tensor as EigenVecotr and EigenConstVector. template struct EigenVector { - using EigenVector = - Eigen::TensorMap, - Eigen::Aligned>; + using Type = Eigen::TensorMap, + Eigen::Aligned>; - using EigenConstVector = + using ConstType = Eigen::TensorMap, Eigen::Aligned>; @@ -82,13 +80,10 @@ struct EigenVector { // Interpret paddle::platform::Tensor as EigenMatrix and EigenConstMatrix. template struct EigenMatrix { - template - using EigenMatrix = - Eigen::TensorMap, - Eigen::Aligned>; + using Type = Eigen::TensorMap, + Eigen::Aligned>; - template - using EigenConstMatrix = + using ConstType = Eigen::TensorMap, Eigen::Aligned>; diff --git a/paddle/framework/eigen_test.cc b/paddle/framework/eigen_test.cc index c5f27a3298..23eec7533f 100644 --- a/paddle/framework/eigen_test.cc +++ b/paddle/framework/eigen_test.cc @@ -12,26 +12,32 @@ */ #include "paddle/framework/eigen.h" - #include -#include "paddle/framework/tensor.h" +namespace paddle { +namespace framework { -TEST(Eigen, Tensor) { - using paddle::platform::Tensor; - using paddle::platform::EigenTensor; - using paddle::platform::make_ddim; +TEST(EigenDim, From) { + EigenDim<3>::Type ed = EigenDim<3>::From(make_ddim({1, 2, 3})); + EXPECT_EQ(1, ed[0]); + EXPECT_EQ(2, ed[1]); + EXPECT_EQ(3, ed[2]); +} +TEST(Eigen, Tensor) { Tensor t; - float* p = t.mutable_data(make_ddim({1, 2, 3}), CPUPlace()); + float* p = t.mutable_data(make_ddim({1, 2, 3}), platform::CPUPlace()); for (int i = 0; i < 1 * 2 * 3; i++) { p[i] = static_cast(i); } - EigenTensor::Type et = EigenTensor::From(t); + EigenTensor::Type et = EigenTensor::From(t); // TODO: check the content of et. } TEST(Eigen, Vector) {} TEST(Eigen, Matrix) {} + +} // namespace platform +} // namespace paddle diff --git a/paddle/framework/tensor.h b/paddle/framework/tensor.h index 405393fb11..8fbf42e7f6 100644 --- a/paddle/framework/tensor.h +++ b/paddle/framework/tensor.h @@ -37,13 +37,13 @@ class Tensor { template friend struct paddle::pybind::details::CastToPyBufferImpl; - template + template friend struct EigenTensor; - template + template friend struct EigenVector; - template + template friend struct EigenMatrix; public: @@ -57,7 +57,7 @@ class Tensor { } template - T* raw_data() const { + T* data() { CheckDims(); return reinterpret_cast(reinterpret_cast(holder_->ptr()) + offset_); From 0a0b4caaa7cea5c2b205cc58cef08cdfb48de3c1 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 19 Jul 2017 13:07:28 +0800 Subject: [PATCH 13/24] Change Operator::create use py::bytes not std::string --- paddle/pybind/pybind.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paddle/pybind/pybind.cc b/paddle/pybind/pybind.cc index e0f4c02459..7e84550f77 100644 --- a/paddle/pybind/pybind.cc +++ b/paddle/pybind/pybind.cc @@ -110,7 +110,7 @@ All parameter, weight, gradient are variables in Paddle. py::class_(m, "Operator") .def("__str__", &pd::OperatorBase::DebugString) .def_static("create", - [](const std::string& protobin) { + [](py::bytes protobin) { pd::OpDesc desc; PADDLE_ENFORCE(desc.ParsePartialFromString(protobin), "Cannot parse user input to OpDesc"); From d9fa6159b7b9109e76c8841388c7811eeac2eb6b Mon Sep 17 00:00:00 2001 From: qijun Date: Wed, 19 Jul 2017 14:06:58 +0800 Subject: [PATCH 14/24] add Flatten method to EigenVector --- paddle/framework/eigen.h | 15 +++++++++++++-- paddle/framework/eigen_test.cc | 6 +++++- paddle/operators/add_op.h | 5 +++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/paddle/framework/eigen.h b/paddle/framework/eigen.h index cd87b042df..f5865635be 100644 --- a/paddle/framework/eigen.h +++ b/paddle/framework/eigen.h @@ -23,7 +23,7 @@ namespace framework { // EigenDim converts paddle::platform::DDim into Eigen::DSizes. template struct EigenDim { - typedef Eigen::DSizes Type; + using Type = Eigen::DSizes; static Type From(const DDim& dims) { PADDLE_ENFORCE(arity(dims) == D, "D must match arity(DDim)"); @@ -69,12 +69,23 @@ struct EigenVector { using ConstType = Eigen::TensorMap, Eigen::Aligned>; - + // From is to transfer a one dimension Tensor into a one dimension EigenVector static Type From(Tensor& tensor) { return EigenTensor::From(tensor); } + // Flatten is to reshape a Tensor into a one dimension EigenVector + static Type Flatten(Tensor& tensor) { + return EigenTensor::From( + tensor, make_ddim({static_cast(product(tensor.dims_))})); + } + static ConstType From(const Tensor& tensor) { return EigenTensor::From(tensor); } + + static ConstType Flatten(const Tensor& tensor) { + return EigenTensor::From( + tensor, make_ddim({static_cast(product(tensor.dims_))})); + } }; // Interpret paddle::platform::Tensor as EigenMatrix and EigenConstMatrix. diff --git a/paddle/framework/eigen_test.cc b/paddle/framework/eigen_test.cc index 23eec7533f..eca2dce60e 100644 --- a/paddle/framework/eigen_test.cc +++ b/paddle/framework/eigen_test.cc @@ -32,6 +32,10 @@ TEST(Eigen, Tensor) { } EigenTensor::Type et = EigenTensor::From(t); + + for (int i = 0; i < 1 * 2 * 3; i++) { + EXPECT_EQ(et(i), i); + } // TODO: check the content of et. } @@ -39,5 +43,5 @@ TEST(Eigen, Vector) {} TEST(Eigen, Matrix) {} -} // namespace platform +} // namespace framework } // namespace paddle diff --git a/paddle/operators/add_op.h b/paddle/operators/add_op.h index e7c106a23f..39d54a63bd 100644 --- a/paddle/operators/add_op.h +++ b/paddle/operators/add_op.h @@ -30,9 +30,10 @@ public: output->mutable_data(context.GetPlace()); - framework::EigenVector::From(*output).device( + framework::EigenVector::Flatten(*output).device( *(context.GetEigenDevice())) = - framework::EigenVector(*input0) + framework::EigenVector(*input1); + framework::EigenVector::Flatten(input0) + + framework::EigenVector::Flatten(input1); } }; From cff8762f2628e5abf562387bc076f23c6c029f7c Mon Sep 17 00:00:00 2001 From: qijun Date: Wed, 19 Jul 2017 14:33:07 +0800 Subject: [PATCH 15/24] add more uinttest for EigenTensor --- paddle/framework/eigen_test.cc | 65 +++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/paddle/framework/eigen_test.cc b/paddle/framework/eigen_test.cc index eca2dce60e..b954c8d857 100644 --- a/paddle/framework/eigen_test.cc +++ b/paddle/framework/eigen_test.cc @@ -33,15 +33,72 @@ TEST(Eigen, Tensor) { EigenTensor::Type et = EigenTensor::From(t); + EXPECT_EQ(1, et.dimension(0)); + EXPECT_EQ(2, et.dimension(1)); + EXPECT_EQ(3, et.dimension(2)); + + for (int i = 0; i < 1; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 3; k++) { + EXPECT_EQ((i * 2 + j) * 3 + k, et(i, j, k)); + } + } + } + for (int i = 0; i < 1 * 2 * 3; i++) { + EXPECT_EQ(i, et(i)); + } +} + +TEST(Eigen, VectorFrom) { + Tensor t; + float* p = t.mutable_data(make_ddim({6}), platform::CPUPlace()); + for (int i = 0; i < 6; i++) { + p[i] = static_cast(i); + } + + EigenVector::Type ev = EigenVector::From(t); + + EXPECT_EQ(6, ev.dimension(0)); + + for (int i = 0; i < 6; i++) { + EXPECT_EQ(i, ev(i)); + } +} + +TEST(Eigen, VectorFlatten) { + Tensor t; + float* p = t.mutable_data(make_ddim({1, 2, 3}), platform::CPUPlace()); + for (int i = 0; i < 1 * 2 * 3; i++) { + p[i] = static_cast(i); + } + + EigenVector::Type ev = EigenVector::Flatten(t); + + EXPECT_EQ(1 * 2 * 3, ev.dimension(0)); + for (int i = 0; i < 1 * 2 * 3; i++) { - EXPECT_EQ(et(i), i); + EXPECT_EQ(i, ev(i)); } - // TODO: check the content of et. } -TEST(Eigen, Vector) {} +TEST(Eigen, Matrix) { + Tensor t; + float* p = t.mutable_data(make_ddim({2, 3}), platform::CPUPlace()); + for (int i = 0; i < 2 * 3; i++) { + p[i] = static_cast(i); + } + + EigenMatrix::Type em = EigenMatrix::From(t); -TEST(Eigen, Matrix) {} + EXPECT_EQ(2, em.dimension(0)); + EXPECT_EQ(3, em.dimension(1)); + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 3; j++) { + EXPECT_EQ(i * 3 + j, em(i, j)); + } + } +} } // namespace framework } // namespace paddle From fab896c5a0219f2ffdc2ca034106407a98ddce65 Mon Sep 17 00:00:00 2001 From: liaogang Date: Wed, 19 Jul 2017 15:01:29 +0800 Subject: [PATCH 16/24] Remove using namespace --- paddle/platform/enforce_test.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/paddle/platform/enforce_test.cc b/paddle/platform/enforce_test.cc index 0a7ccd0819..d7152f8150 100644 --- a/paddle/platform/enforce_test.cc +++ b/paddle/platform/enforce_test.cc @@ -12,8 +12,6 @@ limitations under the License. */ #include "paddle/platform/enforce.h" #include "gtest/gtest.h" -using namespace paddle; - TEST(ENFORCE, OK) { PADDLE_ENFORCE(true, "Enforce is ok %d now %f", 123, 0.345); size_t val = 1; From 97c2a9a9698b8e8364ed99b66ea4232c527ed042 Mon Sep 17 00:00:00 2001 From: liaogang Date: Wed, 19 Jul 2017 16:43:56 +0800 Subject: [PATCH 17/24] Fix: compiler error under gpu --- paddle/platform/enforce.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/paddle/platform/enforce.h b/paddle/platform/enforce.h index b6707659f2..6c1cd443c9 100644 --- a/paddle/platform/enforce.h +++ b/paddle/platform/enforce.h @@ -76,7 +76,7 @@ inline void throw_on_error(cudnnStatus_t stat, const Args&... args) { } else { // clang-format off throw std::runtime_error( - platform::dynload::cudnnGetErrorString(stat) + ", " + + platform::dynload::cudnnGetErrorString(stat) + string::Sprintf(args...) + string::Sprintf(" at [%s:%s];", __FILE__, __LINE__)); // clang-format on @@ -107,7 +107,8 @@ inline void throw_on_error(cublasStatus_t stat, const Args&... args) { } else if (stat == CUBLAS_STATUS_LICENSE_ERROR) { ss << "CUBLAS: license error"; } - throw std::runtime_error(ss + ", " + string::Sprintf(args...) + + ss << ", "; + throw std::runtime_error(ss + string::Sprintf(args...) + string::Sprintf(" at [%s:%s];", __FILE__, __LINE__)); } From 57c27b4e0013e4d3f51b41ae6950f70ae11be2e1 Mon Sep 17 00:00:00 2001 From: qijun Date: Wed, 19 Jul 2017 17:11:49 +0800 Subject: [PATCH 18/24] make EigenTensor default unaligned and follow comments --- paddle/framework/eigen.h | 53 +++++++++++---------------------------- paddle/framework/tensor.h | 7 ++---- 2 files changed, 16 insertions(+), 44 deletions(-) diff --git a/paddle/framework/eigen.h b/paddle/framework/eigen.h index f5865635be..4ba4fd4d11 100644 --- a/paddle/framework/eigen.h +++ b/paddle/framework/eigen.h @@ -36,14 +36,15 @@ struct EigenDim { }; // Interpret paddle::platform::Tensor as EigenTensor and EigenConstTensor. -template +template struct EigenTensor { - using Type = Eigen::TensorMap, - Eigen::Aligned>; + // TODO(qijun) Now, default type in unaligned, and we will make a benchmark on + // the speed of aligned and unaligned version in future. + using Type = Eigen::TensorMap>; using ConstType = - Eigen::TensorMap, - Eigen::Aligned>; + Eigen::TensorMap>; static Type From(Tensor& tensor, DDim dims) { return Type(tensor.data(), EigenDim::From(dims)); @@ -60,50 +61,24 @@ struct EigenTensor { } }; -// Interpret paddle::platform::Tensor as EigenVecotr and EigenConstVector. -template -struct EigenVector { - using Type = Eigen::TensorMap, - Eigen::Aligned>; - - using ConstType = - Eigen::TensorMap, - Eigen::Aligned>; - // From is to transfer a one dimension Tensor into a one dimension EigenVector - static Type From(Tensor& tensor) { return EigenTensor::From(tensor); } - +template +struct EigenVector : public EigenTensor { // Flatten is to reshape a Tensor into a one dimension EigenVector - static Type Flatten(Tensor& tensor) { + static typename EigenTensor::Type Flatten(Tensor& tensor) { return EigenTensor::From( tensor, make_ddim({static_cast(product(tensor.dims_))})); } - static ConstType From(const Tensor& tensor) { - return EigenTensor::From(tensor); - } - - static ConstType Flatten(const Tensor& tensor) { + static typename EigenTensor::ConstType Flatten(const Tensor& tensor) { return EigenTensor::From( tensor, make_ddim({static_cast(product(tensor.dims_))})); } }; -// Interpret paddle::platform::Tensor as EigenMatrix and EigenConstMatrix. -template -struct EigenMatrix { - using Type = Eigen::TensorMap, - Eigen::Aligned>; - - using ConstType = - Eigen::TensorMap, - Eigen::Aligned>; - - static Type From(Tensor& tensor) { return EigenTensor::From(tensor); } - - static ConstType From(const Tensor& tensor) { - return EigenTensor::From(tensor); - } -}; +template +using EigenMatrix = EigenTensor; } // namespace framework } // namespace paddle diff --git a/paddle/framework/tensor.h b/paddle/framework/tensor.h index 8fbf42e7f6..8fd131cf89 100644 --- a/paddle/framework/tensor.h +++ b/paddle/framework/tensor.h @@ -37,15 +37,12 @@ class Tensor { template friend struct paddle::pybind::details::CastToPyBufferImpl; - template + template friend struct EigenTensor; - template + template friend struct EigenVector; - template - friend struct EigenMatrix; - public: Tensor() : offset_(0) {} From d6d057b4e8187df049f6f3ad7879fa045f2fc816 Mon Sep 17 00:00:00 2001 From: qijun Date: Wed, 19 Jul 2017 20:21:49 +0800 Subject: [PATCH 19/24] change EQ to NEAR for float value --- paddle/framework/eigen_test.cc | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/paddle/framework/eigen_test.cc b/paddle/framework/eigen_test.cc index b954c8d857..a9fa728e49 100644 --- a/paddle/framework/eigen_test.cc +++ b/paddle/framework/eigen_test.cc @@ -19,9 +19,9 @@ namespace framework { TEST(EigenDim, From) { EigenDim<3>::Type ed = EigenDim<3>::From(make_ddim({1, 2, 3})); - EXPECT_EQ(1, ed[0]); - EXPECT_EQ(2, ed[1]); - EXPECT_EQ(3, ed[2]); + ASSERT_EQ(1, ed[0]); + ASSERT_EQ(2, ed[1]); + ASSERT_EQ(3, ed[2]); } TEST(Eigen, Tensor) { @@ -33,20 +33,17 @@ TEST(Eigen, Tensor) { EigenTensor::Type et = EigenTensor::From(t); - EXPECT_EQ(1, et.dimension(0)); - EXPECT_EQ(2, et.dimension(1)); - EXPECT_EQ(3, et.dimension(2)); + ASSERT_EQ(1, et.dimension(0)); + ASSERT_EQ(2, et.dimension(1)); + ASSERT_EQ(3, et.dimension(2)); for (int i = 0; i < 1; i++) { for (int j = 0; j < 2; j++) { for (int k = 0; k < 3; k++) { - EXPECT_EQ((i * 2 + j) * 3 + k, et(i, j, k)); + ASSERT_NEAR((i * 2 + j) * 3 + k, et(i, j, k), 1e-6f); } } } - for (int i = 0; i < 1 * 2 * 3; i++) { - EXPECT_EQ(i, et(i)); - } } TEST(Eigen, VectorFrom) { @@ -58,10 +55,10 @@ TEST(Eigen, VectorFrom) { EigenVector::Type ev = EigenVector::From(t); - EXPECT_EQ(6, ev.dimension(0)); + ASSERT_EQ(6, ev.dimension(0)); for (int i = 0; i < 6; i++) { - EXPECT_EQ(i, ev(i)); + ASSERT_NEAR(i, ev(i), 1e-6f); } } @@ -74,10 +71,10 @@ TEST(Eigen, VectorFlatten) { EigenVector::Type ev = EigenVector::Flatten(t); - EXPECT_EQ(1 * 2 * 3, ev.dimension(0)); + ASSERT_EQ(1 * 2 * 3, ev.dimension(0)); for (int i = 0; i < 1 * 2 * 3; i++) { - EXPECT_EQ(i, ev(i)); + ASSERT_NEAR(i, ev(i), 1e-6f); } } @@ -90,12 +87,12 @@ TEST(Eigen, Matrix) { EigenMatrix::Type em = EigenMatrix::From(t); - EXPECT_EQ(2, em.dimension(0)); - EXPECT_EQ(3, em.dimension(1)); + ASSERT_EQ(2, em.dimension(0)); + ASSERT_EQ(3, em.dimension(1)); for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { - EXPECT_EQ(i * 3 + j, em(i, j)); + ASSERT_NEAR(i * 3 + j, em(i, j), 1e-6f); } } } From 2d2ee47bda7ad98956b914f2d81faf5e09b09eef Mon Sep 17 00:00:00 2001 From: liaogang Date: Wed, 19 Jul 2017 20:24:07 +0800 Subject: [PATCH 20/24] FIX: fix string --- paddle/platform/enforce.h | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/paddle/platform/enforce.h b/paddle/platform/enforce.h index 6c1cd443c9..5d440dec48 100644 --- a/paddle/platform/enforce.h +++ b/paddle/platform/enforce.h @@ -85,30 +85,29 @@ inline void throw_on_error(cudnnStatus_t stat, const Args&... args) { template inline void throw_on_error(cublasStatus_t stat, const Args&... args) { - std::stringstream ss; + std::string err; if (stat == CUBLAS_STATUS_SUCCESS) { return; } else if (stat == CUBLAS_STATUS_NOT_INITIALIZED) { - ss << "CUBLAS: not initialized"; + err = "CUBLAS: not initialized, "; } else if (stat == CUBLAS_STATUS_ALLOC_FAILED) { - ss << "CUBLAS: alloc failed"; + err = "CUBLAS: alloc failed, "; } else if (stat == CUBLAS_STATUS_INVALID_VALUE) { - ss << "CUBLAS: invalid value"; + err = "CUBLAS: invalid value, "; } else if (stat == CUBLAS_STATUS_ARCH_MISMATCH) { - ss << "CUBLAS: arch mismatch"; + err = "CUBLAS: arch mismatch, "; } else if (stat == CUBLAS_STATUS_MAPPING_ERROR) { - ss << "CUBLAS: mapping error"; + err = "CUBLAS: mapping error, "; } else if (stat == CUBLAS_STATUS_EXECUTION_FAILED) { - ss << "CUBLAS: execution failed"; + err = "CUBLAS: execution failed, "; } else if (stat == CUBLAS_STATUS_INTERNAL_ERROR) { - ss << "CUBLAS: internal error"; + err = "CUBLAS: internal error, "; } else if (stat == CUBLAS_STATUS_NOT_SUPPORTED) { - ss << "CUBLAS: not supported"; + err = "CUBLAS: not supported, "; } else if (stat == CUBLAS_STATUS_LICENSE_ERROR) { - ss << "CUBLAS: license error"; + err = "CUBLAS: license error, "; } - ss << ", "; - throw std::runtime_error(ss + string::Sprintf(args...) + + throw std::runtime_error(err + string::Sprintf(args...) + string::Sprintf(" at [%s:%s];", __FILE__, __LINE__)); } From e3b27d19982b6eef33329ab0e9dcf718dd4c343e Mon Sep 17 00:00:00 2001 From: Qiao Longfei Date: Wed, 19 Jul 2017 22:30:43 +0800 Subject: [PATCH 21/24] Add sgd op (#2950) * a simplest SGD op --- paddle/operators/CMakeLists.txt | 2 + paddle/operators/sgd_op.cc | 61 +++++++++++++++++++ paddle/operators/sgd_op.cu | 5 ++ paddle/operators/sgd_op.h | 39 ++++++++++++ paddle/operators/sgd_op_test.cc | 22 +++++++ paddle/pybind/CMakeLists.txt | 2 +- paddle/pybind/pybind.cc | 1 + .../paddle/v2/framework/tests/CMakeLists.txt | 2 +- .../paddle/v2/framework/tests/test_sgd_op.py | 18 ++++++ 9 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 paddle/operators/sgd_op.cc create mode 100644 paddle/operators/sgd_op.cu create mode 100644 paddle/operators/sgd_op.h create mode 100644 paddle/operators/sgd_op_test.cc create mode 100644 python/paddle/v2/framework/tests/test_sgd_op.py diff --git a/paddle/operators/CMakeLists.txt b/paddle/operators/CMakeLists.txt index bc64bfd7ec..a37720e509 100644 --- a/paddle/operators/CMakeLists.txt +++ b/paddle/operators/CMakeLists.txt @@ -51,3 +51,5 @@ op_library(softmax_op SRCS softmax_op.cc softmax_op.cu) op_library(fc_op SRCS fc_op.cc DEPS mul_op rowwise_add_op sigmoid_op softmax_op net) + +op_library(sgd_op SRCS sgd_op.cc sgd_op.cu) diff --git a/paddle/operators/sgd_op.cc b/paddle/operators/sgd_op.cc new file mode 100644 index 0000000000..04df87a3ad --- /dev/null +++ b/paddle/operators/sgd_op.cc @@ -0,0 +1,61 @@ +/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#include "paddle/operators/sgd_op.h" +#include "paddle/framework/op_registry.h" +#include "paddle/framework/tensor.h" + +namespace paddle { +namespace operators { + +class SGDOp : public framework::OperatorWithKernel { +protected: + void InferShape( + const std::vector &inputs, + const std::vector &outputs) const override { + PADDLE_ENFORCE(inputs.size() == 2, "Input size of SGDOp must be two"); + PADDLE_ENFORCE(outputs.size() == 1, "Output size of SGDOp must be one"); + PADDLE_ENFORCE(inputs[0] != nullptr, "inputs[0] mast be set"); + PADDLE_ENFORCE(inputs[1] != nullptr, "inputs[1] mast be set"); + PADDLE_ENFORCE(outputs[0] != nullptr, "outputs[0] mast be set"); + PADDLE_ENFORCE(inputs[0]->dims() == inputs[1]->dims(), + "Two input of SGD Op's dimension must be same."); + outputs[0]->set_dims(inputs[0]->dims()); + } +}; + +class SGDOpMaker : public framework::OpProtoAndCheckerMaker { +public: + SGDOpMaker(framework::OpProto *proto, framework::OpAttrChecker *op_checker) + : framework::OpProtoAndCheckerMaker(proto, op_checker) { + AddInput("param", "input parameter"); + AddInput("grad", "input gradient"); + AddOutput("param_out", "output parameter"); + AddAttr("learning_rate", "learning rate of sgd"); + AddComment(R"DOC( + +Simplest sgd algorithm. + +param_out = param - learning_rate * grad; + +)DOC"); + } +}; +} // namespace operators +} // namespace paddle + +REGISTER_OP(sgd, paddle::operators::SGDOp, paddle::operators::SGDOpMaker); +typedef paddle::operators::SGDOpKernel<::paddle::platform::CPUPlace, float> + SGDOpKernel_CPU_float; +REGISTER_OP_CPU_KERNEL(sgd, SGDOpKernel_CPU_float); diff --git a/paddle/operators/sgd_op.cu b/paddle/operators/sgd_op.cu new file mode 100644 index 0000000000..400425db10 --- /dev/null +++ b/paddle/operators/sgd_op.cu @@ -0,0 +1,5 @@ +#include "paddle/operators/sgd_op.h" +#include "paddle/framework/op_registry.h" + +typedef paddle::operators::SGDOpKernel<::paddle::platform::GPUPlace, float> SGDOpKernel_GPU_float; +REGISTER_OP_GPU_KERNEL(sgd, SGDOpKernel_GPU_float); \ No newline at end of file diff --git a/paddle/operators/sgd_op.h b/paddle/operators/sgd_op.h new file mode 100644 index 0000000000..2ee21ef8f9 --- /dev/null +++ b/paddle/operators/sgd_op.h @@ -0,0 +1,39 @@ +/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#pragma once +#include "glog/logging.h" +#include "paddle/framework/operator.h" + +namespace paddle { +namespace operators { + +template +class SGDOpKernel : public framework::OpKernel { +public: + void Compute(const framework::KernelContext& ctx) const override { + auto param = ctx.Input("param")->Get(); + auto grad = ctx.Input("grad")->Get(); + auto* param_out = ctx.Output(0)->GetMutable(); + float lr = ctx.op_.GetAttr("learning_rate"); + + param_out->mutable_data(ctx.GetPlace()); + + param_out->flat().device(*(ctx.GetEigenDevice())) = + param.flat() - lr * grad.flat(); + } +}; + +} // namespace operators +} // namespace paddle diff --git a/paddle/operators/sgd_op_test.cc b/paddle/operators/sgd_op_test.cc new file mode 100644 index 0000000000..75137259f5 --- /dev/null +++ b/paddle/operators/sgd_op_test.cc @@ -0,0 +1,22 @@ +/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#include +#include +USE_OP(sgd); +TEST(SGDOp, GetOpProto) { + auto& protos = paddle::framework::OpRegistry::protos(); + auto it = protos.find("sgd"); + ASSERT_NE(it, protos.end()); +} diff --git a/paddle/pybind/CMakeLists.txt b/paddle/pybind/CMakeLists.txt index 29fb29c7c1..6354dd211d 100644 --- a/paddle/pybind/CMakeLists.txt +++ b/paddle/pybind/CMakeLists.txt @@ -1,2 +1,2 @@ cc_library(paddle_pybind SHARED SRCS pybind.cc DEPS pybind python - add_op fc_op) + add_op fc_op sgd_op) diff --git a/paddle/pybind/pybind.cc b/paddle/pybind/pybind.cc index 7e84550f77..54707a2859 100644 --- a/paddle/pybind/pybind.cc +++ b/paddle/pybind/pybind.cc @@ -28,6 +28,7 @@ namespace pd = paddle::framework; USE_OP(add_two); USE_OP_WITHOUT_KERNEL(fc); +USE_OP(sgd); PYBIND11_PLUGIN(core) { py::module m("core", "C++ core of Paddle Paddle"); diff --git a/python/paddle/v2/framework/tests/CMakeLists.txt b/python/paddle/v2/framework/tests/CMakeLists.txt index f71009aa85..ec076e40c9 100644 --- a/python/paddle/v2/framework/tests/CMakeLists.txt +++ b/python/paddle/v2/framework/tests/CMakeLists.txt @@ -1,3 +1,3 @@ add_python_test(test_framework test_protobuf.py test_scope.py test_default_scope_funcs.py test_op_creation_methods.py - test_tensor.py test_fc_op.py test_add_two_op.py) + test_tensor.py test_fc_op.py test_add_two_op.py test_sgd_op.py) diff --git a/python/paddle/v2/framework/tests/test_sgd_op.py b/python/paddle/v2/framework/tests/test_sgd_op.py new file mode 100644 index 0000000000..405d73b224 --- /dev/null +++ b/python/paddle/v2/framework/tests/test_sgd_op.py @@ -0,0 +1,18 @@ +import unittest +import numpy +from op_test_util import OpTestMeta + + +class TestSGD(unittest.TestCase): + __metaclass__ = OpTestMeta + + def setUp(self): + self.type = "sgd" + self.param = numpy.random.random((342, 345)).astype("float32") + self.grad = numpy.random.random((342, 345)).astype("float32") + self.learning_rate = 0.1 + self.param_out = self.param - self.learning_rate * self.grad + + +if __name__ == "__main__": + unittest.main() From 5e8a4f16c77333f887656fff21ec2357f8f83790 Mon Sep 17 00:00:00 2001 From: liaogang Date: Wed, 19 Jul 2017 22:33:28 +0800 Subject: [PATCH 22/24] Fix conflcts --- paddle/framework/tensor.h | 1 - 1 file changed, 1 deletion(-) diff --git a/paddle/framework/tensor.h b/paddle/framework/tensor.h index 0f99fc89f8..93c6fad5d3 100644 --- a/paddle/framework/tensor.h +++ b/paddle/framework/tensor.h @@ -19,7 +19,6 @@ limitations under the License. */ #include #include #include "paddle/framework/ddim.h" -#include "paddle/framework/tensor_types.h" #include "paddle/memory/memory.h" #include "paddle/platform/enforce.h" #include "paddle/platform/place.h" From e4984f13e9ddaa035234f0672781b6e324591ed8 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Wed, 19 Jul 2017 23:02:27 +0800 Subject: [PATCH 23/24] fix tensor usage in sgd-op --- paddle/operators/sgd_op.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/paddle/operators/sgd_op.h b/paddle/operators/sgd_op.h index 2ee21ef8f9..4b2d214618 100644 --- a/paddle/operators/sgd_op.h +++ b/paddle/operators/sgd_op.h @@ -14,6 +14,7 @@ limitations under the License. */ #pragma once #include "glog/logging.h" +#include "paddle/framework/eigen.h" #include "paddle/framework/operator.h" namespace paddle { @@ -30,8 +31,10 @@ public: param_out->mutable_data(ctx.GetPlace()); - param_out->flat().device(*(ctx.GetEigenDevice())) = - param.flat() - lr * grad.flat(); + framework::EigenVector::Flatten(*param_out) + .device(*(ctx.GetEigenDevice())) = + framework::EigenVector::Flatten(param) - + lr * framework::EigenVector::Flatten(grad); } }; From a98346f4cd1a0468ac2d1d30574607698f7432bc Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 19 Jul 2017 21:06:07 -0500 Subject: [PATCH 24/24] Add comment to `OpTestMeta` (#2968) --- python/paddle/v2/framework/tests/op_test_util.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/python/paddle/v2/framework/tests/op_test_util.py b/python/paddle/v2/framework/tests/op_test_util.py index 237f9b7eb0..b1fa12cc89 100644 --- a/python/paddle/v2/framework/tests/op_test_util.py +++ b/python/paddle/v2/framework/tests/op_test_util.py @@ -5,6 +5,18 @@ import paddle.v2.framework.create_op_creation_methods as creation class OpTestMeta(type): + """ + Operator Test ClassMeta. + + It injects `test_all` method into user's OperatorTest class, to make Python + unittest module run that method. + + The `test_all` read what value is stored in `self`. It use self's values to + create and run a operator, and check whether that op is OK or not. + + See `test_add_two_op` for example usage. + """ + def __new__(cls, name, bases, attrs): obj = super(OpTestMeta, cls).__new__(cls, name, bases, attrs)