parallel_executor.cc 4.7 KB
Newer Older
Y
Yang Yang 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

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/fluid/framework/parallel_executor.h"
Y
Yu Yang 已提交
16

Y
Yu Yang 已提交
17
#include "ThreadPool.h"
Y
Yu Yang 已提交
18

Y
Yu Yang 已提交
19
#include "paddle/fluid/platform/nccl_helper.h"
Y
Yang Yang 已提交
20

Y
Yu Yang 已提交
21 22 23
#include "paddle/fluid/framework/details/multi_devices_graph_builder.h"
#include "paddle/fluid/framework/details/threaded_ssa_graph_executor.h"

Y
Yang Yang 已提交
24
namespace paddle {
Y
Yu Yang 已提交
25 26
namespace framework {

Y
Yu Yang 已提交
27 28 29
class ParallelExecutorPrivate {
 public:
  explicit ParallelExecutorPrivate(const std::vector<platform::Place> &places)
Y
Yu Yang 已提交
30
      : places_(places) {}
Y
Yu Yang 已提交
31 32 33 34

  std::vector<platform::Place> places_;
  std::vector<Scope *> local_scopes_;
  Scope *global_scope_;
Y
Yu Yang 已提交
35
  std::unique_ptr<details::SSAGraphExecutor> executor_;
Y
Yu Yang 已提交
36

Y
Yu Yang 已提交
37
#ifdef PADDLE_WITH_CUDA
Y
Yu Yang 已提交
38
  std::unique_ptr<platform::NCCLContextMap> nccl_ctxs_;
Y
Yu Yang 已提交
39
#endif
Y
Yu Yang 已提交
40 41
};

Y
Yu Yang 已提交
42
ParallelExecutor::ParallelExecutor(
Y
Yu Yang 已提交
43
    size_t num_threads, const std::vector<platform::Place> &places,
Y
Yu Yang 已提交
44 45 46
    const std::unordered_set<std::string> &params,
    const ProgramDesc &startup_program, const ProgramDesc &main_program,
    const std::string &loss_var_name, Scope *scope)
Y
Yu Yang 已提交
47
    : member_(new ParallelExecutorPrivate(places)) {
Y
Yu Yang 已提交
48
  member_->global_scope_ = scope;
Y
Yu Yang 已提交
49

Y
Yu Yang 已提交
50 51 52 53
  // Step 1. RunStartupProgram and Bcast the params to devs.
  Executor exe(places[0]);
  exe.Run(startup_program, scope, 0);
  // Create local scopes
Y
Yu Yang 已提交
54 55
  for (size_t i = 0; i < member_->places_.size(); ++i) {
    member_->local_scopes_.push_back(&scope->NewScope());
Y
Yu Yang 已提交
56 57
  }

Y
Yu Yang 已提交
58 59 60 61
// Bcast Parameters to all GPUs
#ifdef PADDLE_WITH_CUDA
  member_->nccl_ctxs_.reset(new platform::NCCLContextMap(member_->places_));
#endif
Y
Yu Yang 已提交
62
  if (platform::is_gpu_place(places[0]) &&
Y
Yu Yang 已提交
63 64
      member_->local_scopes_.size() != 1) {  // Is CUDA
    BCastParamsToGPUs(startup_program);
Y
Yu Yang 已提交
65 66 67 68 69
  }
  // Startup Program has been run. All local scopes has correct parameters.

  // Step 2. Convert main_program to SSA form and dependency graph. Also, insert
  // ncclOp
Y
Yu Yang 已提交
70 71 72
  details::MultiDevSSAGraphBuilder builder(member_->places_, loss_var_name,
                                           params, member_->local_scopes_,
                                           member_->nccl_ctxs_.get());
Y
Yu Yang 已提交
73
  auto graph = builder.Build(main_program);
Y
Yu Yang 已提交
74

Y
Yu Yang 已提交
75
  member_->executor_.reset(new details::ThreadedSSAGraphExecutor(
Y
Yu Yang 已提交
76
      num_threads, true, member_->local_scopes_, places, std::move(graph)));
Y
Yu Yang 已提交
77

Y
Yu Yang 已提交
78
  // Step 3. Create vars in each scope;
Y
Yu Yang 已提交
79
  for (auto *scope : member_->local_scopes_) {
Y
Yu Yang 已提交
80 81 82 83 84 85 86 87
    for (auto *var : main_program.Block(0).AllVars()) {
      if (scope->FindVar(var->Name()) != nullptr) {
        continue;
      }

      InitializeVariable(scope->Var(var->Name()), var->GetType());
    }
  }
Y
Yu Yang 已提交
88 89 90 91
}

void ParallelExecutor::BCastParamsToGPUs(
    const ProgramDesc &startup_program) const {
Y
Yu Yang 已提交
92
#ifdef PADDLE_WITH_CUDA
Y
Yu Yang 已提交
93
  auto *main_scope = member_->local_scopes_[0];
Y
Yu Yang 已提交
94

Y
Yu Yang 已提交
95 96 97 98
  for (auto *var_desc : startup_program.Block(0).AllVars()) {
    if (var_desc->GetType() == proto::VarType::LOD_TENSOR) {
      auto &main_tensor =
          main_scope->FindVar(var_desc->Name())->Get<LoDTensor>();
Y
Yu Yang 已提交
99
      ncclDataType_t data_type = platform::ToNCCLDataType(main_tensor.type());
Y
Yu Yang 已提交
100 101 102
      auto &dims = main_tensor.dims();
      size_t numel = main_tensor.numel();

Y
Yu Yang 已提交
103
      platform::NCCLGroupGuard guard;
Y
Yu Yang 已提交
104

Y
Update  
Yu Yang 已提交
105 106 107 108 109 110
      for (size_t i = 0; i < member_->places_.size(); ++i) {
        auto place = member_->places_[i];
        void *buffer;
        if (i == 0) {
          buffer = const_cast<void *>(main_tensor.data<void>());
        } else {
Y
Yu Yang 已提交
111
          auto local_scope = member_->local_scopes_[i];
Y
Update  
Yu Yang 已提交
112 113 114 115 116
          auto *t = local_scope->Var(var_desc->Name())->GetMutable<LoDTensor>();
          t->Resize(dims);
          buffer = t->mutable_data(place, main_tensor.type());
        }

Y
Yu Yang 已提交
117
        auto &nccl_ctx = member_->nccl_ctxs_->at(place);
Y
Yu Yang 已提交
118 119
        platform::dynload::ncclBcast(buffer, numel, data_type, 0,
                                     nccl_ctx.comm_, nccl_ctx.stream());
Y
Yu Yang 已提交
120
      }
Y
Stash  
Yu Yang 已提交
121
    }
Y
Yu Yang 已提交
122
    member_->nccl_ctxs_->WaitAll();
Y
Stash  
Yu Yang 已提交
123
  }
Y
Yu Yang 已提交
124 125 126 127
#else
  PADDLE_THROW("Not compiled with CUDA");
#endif
}
Y
Yu Yang 已提交
128

Y
Yu Yang 已提交
129 130
void ParallelExecutor::Run(const std::vector<std::string> &fetch_tensors,
                           const std::string &fetched_var_name) {
Y
Yu Yang 已提交
131 132 133
  auto fetch_data = member_->executor_->Run(fetch_tensors);
  *member_->global_scope_->Var(fetched_var_name)->GetMutable<FeedFetchList>() =
      fetch_data;
Y
Yu Yang 已提交
134
}
Y
Yu Yang 已提交
135

Y
Yu Yang 已提交
136
}  // namespace framework
Y
Yang Yang 已提交
137
}  // namespace paddle