From 90d9e5aee891c3ebf576ceb58cde459799cfa13d Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Wed, 31 Oct 2018 14:42:07 +0800 Subject: [PATCH] feat(platform): lazy initialization of devicecontext in pool (#14067) * feat(platform): lazy initialization of devicecontext in pool Use std::async(deferer, []{...}) to lazy initialize DeviceContext in Pool test=develop * Add future includes test=develop --- paddle/fluid/framework/parallel_executor.cc | 6 ++-- paddle/fluid/platform/device_context.cc | 36 ++++++++++----------- paddle/fluid/platform/device_context.h | 7 ++-- 3 files changed, 22 insertions(+), 27 deletions(-) diff --git a/paddle/fluid/framework/parallel_executor.cc b/paddle/fluid/framework/parallel_executor.cc index 4abde1f21e9..a45b9ec7a20 100644 --- a/paddle/fluid/framework/parallel_executor.cc +++ b/paddle/fluid/framework/parallel_executor.cc @@ -303,10 +303,8 @@ void ParallelExecutor::FeedAndSplitTensorIntoLocalScopes( } ParallelExecutor::~ParallelExecutor() { - const auto dev_ctxs = - platform::DeviceContextPool::Instance().GetAllDeviceContexts(); - for (auto &dev_ctx : dev_ctxs) { - dev_ctx->Wait(); + for (auto &p : member_->places_) { + platform::DeviceContextPool::Instance().Get(p)->Wait(); } if (member_->own_local_scope_) { diff --git a/paddle/fluid/platform/device_context.cc b/paddle/fluid/platform/device_context.cc index b0de636de46..924810bd618 100644 --- a/paddle/fluid/platform/device_context.cc +++ b/paddle/fluid/platform/device_context.cc @@ -32,23 +32,25 @@ platform::DeviceContext* DeviceContextPool::Get(const platform::Place& place) { "'Place' is not supported, Please re-compile with WITH_GPU " "option"); } - return it->second.get(); + return it->second.get().get(); } -const std::vector -DeviceContextPool::GetAllDeviceContexts() const { - std::vector all_device_ctx; - all_device_ctx.reserve(device_contexts_.size()); - for (auto& dev_ctx : device_contexts_) { - all_device_ctx.emplace_back(dev_ctx.second.get()); - } - return all_device_ctx; +template +inline void EmplaceDeviceContext( + std::map>>* + map_ptr, + platform::Place p) { + using PtrType = std::unique_ptr; + map_ptr->emplace(p, std::async(std::launch::deferred, [=] { + // lazy evaluation. i.e., only create device context at + // first `Get` + return PtrType(new DevCtx(boost::get(p))); + })); } DeviceContextPool::DeviceContextPool( const std::vector& places) { PADDLE_ENFORCE_GT(places.size(), 0); - using PtrType = std::unique_ptr; std::set set; for (auto& p : places) { set.insert(p); @@ -57,16 +59,13 @@ DeviceContextPool::DeviceContextPool( for (auto& p : set) { if (platform::is_cpu_place(p)) { #ifdef PADDLE_WITH_MKLDNN - device_contexts_.emplace( - p, PtrType(new MKLDNNDeviceContext(boost::get(p)))); + EmplaceDeviceContext(&device_contexts_, p); #else - device_contexts_.emplace( - p, PtrType(new CPUDeviceContext(boost::get(p)))); + EmplaceDeviceContext(&device_contexts_, p); #endif } else if (platform::is_gpu_place(p)) { #ifdef PADDLE_WITH_CUDA - device_contexts_.emplace( - p, PtrType(new CUDADeviceContext(boost::get(p)))); + EmplaceDeviceContext(&device_contexts_, p); #else PADDLE_THROW( "'CUDAPlace' is not supported, Please re-compile with WITH_GPU " @@ -74,9 +73,8 @@ DeviceContextPool::DeviceContextPool( #endif } else if (platform::is_cuda_pinned_place(p)) { #ifdef PADDLE_WITH_CUDA - device_contexts_.emplace( - p, - PtrType(new CUDAPinnedDeviceContext(boost::get(p)))); + EmplaceDeviceContext( + &device_contexts_, p); #else PADDLE_THROW( "'CUDAPlace' is not supported, Please re-compile with WITH_GPU " diff --git a/paddle/fluid/platform/device_context.h b/paddle/fluid/platform/device_context.h index 942e13a7243..0240b9380f3 100644 --- a/paddle/fluid/platform/device_context.h +++ b/paddle/fluid/platform/device_context.h @@ -10,6 +10,7 @@ See the License for the specific language governing permissions and limitations under the License. */ #pragma once +#include // NOLINT #include #include // NOLINT #include @@ -223,9 +224,6 @@ class DeviceContextPool { /*! \brief Return handle of single device context. */ platform::DeviceContext* Get(const platform::Place& place); - /*! \brief Return all the device contexts. */ - const std::vector GetAllDeviceContexts() const; - template const typename DefaultDeviceContextType::TYPE* GetByPlace( const Place& place) { @@ -237,7 +235,8 @@ class DeviceContextPool { private: static DeviceContextPool* pool; - std::map> device_contexts_; + std::map>> + device_contexts_; DISABLE_COPY_AND_ASSIGN(DeviceContextPool); }; -- GitLab