engine.cc 8.2 KB
Newer Older
F
flame 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
// Copyright (c) 2018 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/inference/anakin/engine.h"
#include <algorithm>
#include <cstring>
#include <map>
#include <utility>
#include "paddle/fluid/framework/ddim.h"

using anakin::Precision;
using anakin::OpRunType;
using paddle::framework::LoDTensor;
template <typename T, Precision P, OpRunType O>
using AnakinNetT = anakin::Net<T, P, O>;

template <typename T, Precision P>
using AnakinGraphT = anakin::graph::Graph<T, P>;

namespace paddle {
namespace inference {
namespace anakin {

template <typename TargetT, Precision PrecisionType, OpRunType RunType>
36 37
AnakinEngine<TargetT, PrecisionType, RunType>::AnakinEngine(
    bool need_summary, int device, int max_batch_size,
38
    std::map<std::string, std::vector<int>> max_input_shape,
39
    std::vector<std::string> program_inputs, bool auto_config_layout)
F
flame 已提交
40
    : graph_(new AnakinGraphT<TargetT, PrecisionType>()),
41 42
      net_(new AnakinNetT<TargetT, PrecisionType, RunType>(need_summary)) {
  device_ = device;
43
  max_batch_size_ = max_batch_size;
44
  max_input_shape_ = max_input_shape;
45
  program_inputs_ = program_inputs;
46
  auto_config_layout_ = auto_config_layout;
47
}
F
flame 已提交
48 49 50 51 52 53 54 55 56 57 58 59

template <typename TargetT, Precision PrecisionType, OpRunType RunType>
AnakinEngine<TargetT, PrecisionType, RunType>::~AnakinEngine() {}

template <typename TargetT, Precision PrecisionType, OpRunType RunType>
void AnakinEngine<TargetT, PrecisionType, RunType>::SetInputShape(
    const std::string &name, std::vector<int> shape) {
  graph_->AddOpAttr<::anakin::PTuple<int>>(name, "input_shape",
                                           std::move(shape));
}

template <typename TargetT, Precision PrecisionType, OpRunType RunType>
60
void AnakinEngine<TargetT, PrecisionType, RunType>::InitNet() {
61
  net_->init(*graph_, auto_config_layout_);
F
flame 已提交
62 63 64 65 66 67 68 69 70 71 72
}

template <typename TargetT, Precision PrecisionType, OpRunType RunType>
void AnakinEngine<TargetT, PrecisionType, RunType>::AddOp(
    const std::string &name, const std::string &type,
    const std::vector<std::string> &inputs,
    const std::vector<std::string> &outputs) {
  PADDLE_ENFORCE(graph_->AddOp(name, type, inputs, outputs), "Add operation.");
}

template <typename TargetT, Precision PrecisionType, OpRunType RunType>
73 74 75
void AnakinEngine<TargetT, PrecisionType, RunType>::BindInput(
    const std::map<std::string, framework::LoDTensor *> &inputs) {
#ifdef PADDLE_WITH_CUDA
76
  cudaDeviceSynchronize();
77
#endif
F
flame 已提交
78 79 80
  for (const auto &input : inputs) {
    auto *tensor = input.second;
    auto *data = tensor->data<float>();
81

82
    auto fluid_input_shape = framework::vectorize2int(tensor->dims());
83 84 85
    while (fluid_input_shape.size() < 4) {
      fluid_input_shape.push_back(1);
    }
F
flame 已提交
86
    auto *anakin_input = net_->get_in(input.first);
87 88 89 90
    std::vector<int> max_input_shape = max_input_shape_[input.first];
    int max_shape_sum =
        std::accumulate(max_input_shape.begin(), max_input_shape.end(), 1,
                        std::multiplies<int>());
91 92 93 94 95 96 97 98 99 100 101 102 103
    if (tensor->numel() > max_shape_sum) {
      PADDLE_ENFORCE(std::find(program_inputs_.begin(), program_inputs_.end(),
                               input.first) == program_inputs_.end(),
                     "The anakin input max shape should be greater than"
                     " or equal to the real input shape, Please set the max "
                     "input shape using EnableAnakinEngine");
      VLOG(3) << "Anakin Net will be reset because of the inputs out of range: "
              << input.first;
      graph_->Reshape(input.first, fluid_input_shape);
      net_.reset(new AnakinNetT<TargetT, PrecisionType, RunType>(true));
      net_->init(*graph_);
      anakin_input = net_->get_in(input.first);
    }
104
    anakin_input->reshape(fluid_input_shape);
F
flame 已提交
105
    ::anakin::saber::Tensor<TargetT> tmp_anakin_tensor(data, TargetT(), 0,
106 107
                                                       fluid_input_shape);
    anakin_input->copy_from(tmp_anakin_tensor);
F
flame 已提交
108
  }
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
}

template <typename TargetT, Precision PrecisionType, OpRunType RunType>
void AnakinEngine<TargetT, PrecisionType, RunType>::Execute(
    const std::map<std::string, framework::LoDTensor *> &inputs,
    const std::map<std::string, framework::LoDTensor *> &outputs) {
  BindInput(inputs);
  net_->prediction();
  for (const auto &output : outputs) {
    platform::CPUPlace cpu_place;
    auto *tensor = output.second;
    auto *anakin_output = net_->get_out(output.first);
    auto *anakin_data = anakin_output->data();
    auto anakin_output_shape = anakin_output->valid_shape();
    tensor->Resize(framework::make_ddim(anakin_output_shape));
    auto *fluid_data = tensor->mutable_data<float>(cpu_place);
    memory::Copy(cpu_place, static_cast<void *>(fluid_data), cpu_place,
                 static_cast<void *>(anakin_data),
                 tensor->numel() * sizeof(float));
  }
}

#ifdef PADDLE_WITH_CUDA
template <typename TargetT, Precision PrecisionType, OpRunType RunType>
void AnakinEngine<TargetT, PrecisionType, RunType>::Execute(
    const std::map<std::string, framework::LoDTensor *> &inputs,
    const std::map<std::string, framework::LoDTensor *> &outputs,
    cudaStream_t stream) {
  BindInput(inputs);
138
  net_->prediction();
139
  cudaDeviceSynchronize();
F
flame 已提交
140
  for (const auto &output : outputs) {
141
    platform::CUDAPlace gpu_place(device_);
F
flame 已提交
142 143
    auto *tensor = output.second;
    auto *anakin_output = net_->get_out(output.first);
144
    auto *anakin_data = anakin_output->data();
145
    auto anakin_output_shape = anakin_output->valid_shape();
146 147 148 149 150
    tensor->Resize(framework::make_ddim(anakin_output_shape));
    auto *fluid_data = tensor->mutable_data<float>(gpu_place);
    memory::Copy(gpu_place, static_cast<void *>(fluid_data), gpu_place,
                 static_cast<void *>(anakin_data),
                 tensor->numel() * sizeof(float), stream);
F
flame 已提交
151
  }
152
  cudaDeviceSynchronize();
F
flame 已提交
153
}
154
#endif
F
flame 已提交
155 156 157

template <typename TargetT, Precision PrecisionType, OpRunType RunType>
void AnakinEngine<TargetT, PrecisionType, RunType>::Freeze() {
158
  PADDLE_ENFORCE(graph_->Freeze(), "Freeze anakin subgraph.");
F
flame 已提交
159 160 161 162 163 164 165
}

template <typename TargetT, Precision PrecisionType, OpRunType RunType>
void AnakinEngine<TargetT, PrecisionType, RunType>::Optimize() {
  PADDLE_ENFORCE(graph_->Optimize(), "Graph optimization.");
}

166 167 168 169 170 171
template <typename TargetT, Precision PrecisionType, OpRunType RunType>
void AnakinEngine<TargetT, PrecisionType, RunType>::RegistBlock(
    ::anakin::PBlock<TargetT> *block_p) {
  PADDLE_ENFORCE(graph_->RegistBlock(block_p), "Block register.");
}

F
flame 已提交
172 173 174 175 176 177 178 179
template <typename TargetT, Precision PrecisionType, OpRunType RunType>
std::unique_ptr<AnakinEngine<TargetT, PrecisionType, RunType>>
AnakinEngine<TargetT, PrecisionType, RunType>::Clone() {
  auto *engine = new AnakinEngine();
  engine->net_ = std::move(net_->Clone());
  return std::unique_ptr<AnakinEngine>(engine);
}

180
#ifdef PADDLE_WITH_CUDA
F
flame 已提交
181
template class AnakinEngine<::anakin::saber::NV, ::anakin::Precision::FP32>;
182 183 184 185 186 187
template class AnakinEngineManager<::anakin::saber::NV,
                                   ::anakin::Precision::FP32>;

template class AnakinEngine<::anakin::saber::NV, ::anakin::Precision::INT8>;
template class AnakinEngineManager<::anakin::saber::NV,
                                   ::anakin::Precision::INT8>;
188 189 190
#endif

template class AnakinEngine<::anakin::saber::X86, ::anakin::Precision::FP32>;
191 192 193 194 195
template class AnakinEngineManager<::anakin::saber::X86,
                                   ::anakin::Precision::FP32>;
template class AnakinEngine<::anakin::saber::X86, ::anakin::Precision::INT8>;
template class AnakinEngineManager<::anakin::saber::X86,
                                   ::anakin::Precision::INT8>;
196 197

// template class AnakinEngine<::anakin::saber::X86, ::anakin::Precision::FP32>;
F
flame 已提交
198 199 200
}  // namespace anakin
}  // namespace inference
}  // namespace paddle