precision_profiler.h 9.4 KB
Newer Older
Y
Yan Chunwei 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
// Copyright (c) 2019 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.

/*
 * This file implements BasicProfile, a profiler that helps to profile the basic
 * CPU execution. It can display the min, max, average lantency of the execution
 * of each kernel.
 */
#pragma once
#include <string>
#include <vector>
#include "lite/core/program.h"
24 25 26
#ifdef LITE_WITH_OPENCL
#include "lite/kernels/opencl/image_helper.h"
#endif
Y
Yan Chunwei 已提交
27 28 29 30
namespace paddle {
namespace lite {
namespace profile {

T
TianXiaogang 已提交
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
template <typename dtype>
static void write_tensorfile(const Tensor* tensor, const std::string& locate) {
  if (locate.find('/') != std::string::npos) {
    return;
  }
  FILE* fp = fopen(locate.c_str(), "w");
  if (fp == nullptr) {
    LOG(ERROR) << "file open field " << locate;
  } else {
    const dtype* data = tensor->data<dtype>();
    for (int i = 0; i < tensor->numel(); ++i) {
      fprintf(fp, "[%d] %f \n", i, static_cast<float>(data[i]));
    }
  }
  fclose(fp);
}

Y
Yan Chunwei 已提交
48 49 50 51 52
class PrecisionProfiler {
 public:
  explicit PrecisionProfiler(const Instruction* inst) : inst_(inst) {}
  ~PrecisionProfiler() {
    LOG(INFO) << ">> Running kernel: " << inst_->op()->op_info()->Repr()
T
TianXiaogang 已提交
53
              << " on Target " << TargetToStr(inst_->kernel()->target()) << " "
54 55
              << PrecisionToStr(inst_->kernel()->precision()) << " "
              << DataLayoutToStr(inst_->kernel()->layout());
T
TianXiaogang 已提交
56 57
    auto tensor_mean = [](const Tensor* in,
                          PrecisionType ptype,
58 59
                          std::string target_str = "host",
                          std::string layout_str = "nchw",
T
TianXiaogang 已提交
60 61 62 63
                          std::string name = "inst") -> double {
      if (!in->data<int8_t>()) {
        return -99999;
      }
Y
Yan Chunwei 已提交
64 65
      double sum = 0.;
      switch (ptype) {
66
#ifndef LITE_WITH_OPENCL
Y
Yan Chunwei 已提交
67 68
        case PRECISION(kFloat): {
          auto ptr = in->data<float>();
T
TianXiaogang 已提交
69 70 71 72 73 74
          // write_tensorfile<float>(in, name);
          for (int i = 0; i < in->numel(); ++i) {
            sum += ptr[i];
          }
          return sum / in->numel();
        }
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 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 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
#else
        case PRECISION(kFloat): {
          if (layout_str == "ImageDefault") {
            paddle::lite::CLImageConverterDefault default_convertor;
            auto image_shape =
                default_convertor.InitImageDimInfoWith(in->dims());
            size_t im_w = image_shape[0];
            size_t im_h = image_shape[1];
            LOG(INFO) << im_w << " " << im_h;
            std::vector<float> in_data_v(im_w * im_h * 4);
            std::vector<float> real_out_v(in->numel());
            const size_t cl_image2d_row_pitch{0};
            const size_t cl_image2d_slice_pitch{0};
            TargetWrapperCL::ImgcpySync(in_data_v.data(),
                                        in->data<float, cl::Image2D>(),
                                        im_w,
                                        im_h,
                                        cl_image2d_row_pitch,
                                        cl_image2d_slice_pitch,
                                        IoDirection::DtoH);
            default_convertor.ImageToNCHW(
                in_data_v.data(), real_out_v.data(), image_shape, in->dims());
            // write_tensorfile<float>(in, name);
            for (int i = 0; i < real_out_v.size(); ++i) {
              sum += real_out_v[i];
            }
            LOG(INFO) << in->numel();
            return sum / in->numel();
          } else if (target_str == "opencl") {
            std::vector<float> in_data_v(in->numel(), 0);
            TargetWrapperCL::MemcpySync(in_data_v.data(),
                                        in->data<float>(),
                                        in->numel() * sizeof(float),
                                        IoDirection::DtoH);
            for (int i = 0; i < in_data_v.size(); ++i) {
              sum += in_data_v[i];
            }
            LOG(INFO) << in->numel();
            return sum / in->numel();
          } else {
            return -10000;
          }
        }
        case PRECISION(kAny): {
          if (layout_str == "ImageDefault") {
            paddle::lite::CLImageConverterDefault default_convertor;
            auto image_shape =
                default_convertor.InitImageDimInfoWith(in->dims());
            size_t im_w = image_shape[0];
            size_t im_h = image_shape[1];
            LOG(INFO) << im_w << " " << im_h;
            std::vector<float> in_data_v(im_w * im_h * 4);
            std::vector<float> real_out_v(in->numel());
            const size_t cl_image2d_row_pitch{0};
            const size_t cl_image2d_slice_pitch{0};
            TargetWrapperCL::ImgcpySync(in_data_v.data(),
                                        in->data<float, cl::Image2D>(),
                                        im_w,
                                        im_h,
                                        cl_image2d_row_pitch,
                                        cl_image2d_slice_pitch,
                                        IoDirection::DtoH);
            default_convertor.ImageToNCHW(
                in_data_v.data(), real_out_v.data(), image_shape, in->dims());
            // write_tensorfile<float>(in, name);
            for (int i = 0; i < in->numel(); ++i) {
              sum += real_out_v[i];
            }
            LOG(INFO) << in->numel();
            return sum / in->numel();
          } else if (target_str == "opencl") {
            std::vector<float> in_data_v(in->numel(), 0);
            TargetWrapperCL::MemcpySync(in_data_v.data(),
                                        in->data<float>(),
                                        in->numel() * sizeof(float),
                                        IoDirection::DtoH);
            for (int i = 0; i < in_data_v.size(); ++i) {
              sum += in_data_v[i];
            }
            LOG(INFO) << in->numel();
            return sum / in->numel();
          } else {
            return -10000;
          }
        }
#endif
#ifndef LITE_WITH_OPENCL
T
TianXiaogang 已提交
162 163 164
        case PRECISION(kAny): {
          auto ptr = in->data<float>();
          // write_tensorfile<float>(in, name);
Y
Yan Chunwei 已提交
165 166 167 168 169 170 171
          for (int i = 0; i < in->numel(); ++i) {
            sum += ptr[i];
          }
          return sum / in->numel();
        }
        case PRECISION(kInt8): {
          auto ptr = in->data<int8_t>();
T
TianXiaogang 已提交
172
          // write_tensorfile<int8_t>(in, name);
Y
Yan Chunwei 已提交
173 174 175 176 177 178 179
          for (int i = 0; i < in->numel(); ++i) {
            sum += ptr[i];
          }
          return sum / in->numel();
        }
        case PRECISION(kInt32): {
          auto ptr = in->data<int32_t>();
T
TianXiaogang 已提交
180
          // write_tensorfile<int32_t>(in, name);
Y
Yan Chunwei 已提交
181 182 183 184 185
          for (int i = 0; i < in->numel(); ++i) {
            sum += ptr[i];
          }
          return sum / in->numel();
        }
186
#endif
Y
Yan Chunwei 已提交
187 188 189 190 191 192 193 194 195 196 197 198 199 200
        default:
          LOG(INFO) << "unsupport data type: " << PrecisionToStr(ptype);
          return 0.;
      }
    };
    if (inst_->op()->op_info()->Type() != "fetch") {
      auto op = const_cast<lite::OpLite*>(inst_->op());
      auto kernel = inst_->kernel();
      auto op_scope = op->scope();
      auto out_names = op->op_info()->output_names();
      for (auto& out_name : out_names) {
        std::string out_arg_name;
        op->op_info()->GetOutputArgname(out_name, &out_arg_name);
        auto type = kernel->GetOutputDeclType(out_arg_name);
T
TianXiaogang 已提交
201

Y
Yan Chunwei 已提交
202 203
        if (type->IsTensor()) {
          auto tout = op_scope->FindVar(out_name)->GetMutable<Tensor>();
204 205 206 207 208 209
          double mean = tensor_mean(tout,
                                    type->precision(),
                                    TargetToStr(inst_->kernel()->target()),
                                    DataLayoutToStr(inst_->kernel()->layout()),
                                    out_name);
          LOG(INFO) << "go here";
Y
Yan Chunwei 已提交
210 211
          LOG(INFO) << "output name: " << out_name << ", dims: " << tout->dims()
                    << ", precision: " << PrecisionToStr(type->precision())
212 213
                    << " " << TargetToStr(inst_->kernel()->target()) << " "
                    << DataLayoutToStr(inst_->kernel()->layout())
T
TianXiaogang 已提交
214
                    << ", mean value: " << mean << " shape:" << tout->dims();
Y
Yan Chunwei 已提交
215 216 217 218
        } else if (type->IsTensorList()) {
          auto tout =
              op_scope->FindVar(out_name)->GetMutable<std::vector<Tensor>>();
          for (auto& t : *tout) {
219 220 221 222 223 224
            double mean =
                tensor_mean(&t,
                            type->precision(),
                            TargetToStr(inst_->kernel()->target()),
                            DataLayoutToStr(inst_->kernel()->layout()),
                            out_name);
Y
Yan Chunwei 已提交
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
            LOG(INFO) << "output name: " << out_name << ", dims: " << t.dims()
                      << ", precision: " << PrecisionToStr(type->precision())
                      << ", mean value: " << mean;
          }
        }
      }
    }
  }

 private:
  const Instruction* inst_{nullptr};
};

}  // namespace profile
}  // namespace lite
}  // namespace paddle

#define LITE_PRECISION_PROFILE(inst) \
  { auto a = paddle::lite::profile::PrecisionProfiler(&inst); }