io.cpp 12.7 KB
Newer Older
W
wangliu 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/* 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. */
朔-望's avatar
朔-望 已提交
14

L
liuruilong 已提交
15
#include "io.h"
朔-望's avatar
朔-望 已提交
16
#include <fstream>
L
liuruilong 已提交
17
#include <vector>
朔-望's avatar
朔-望 已提交
18

L
liuruilong 已提交
19
#include "common/log.h"
L
liuruilong 已提交
20
#include "common/enforce.h"
L
liuruilong 已提交
21 22
#include "framework/scope.h"
#include "framework/tensor.h"
L
liuruilong 已提交
23 24 25 26 27
#include "framework/operator.h"
#include "framework/lod_tensor.h"
#include "framework/framework.pb-c.h"
#include "framework/program/var_desc.h"
#include "framework/program/program_desc.h"
L
liuruilong 已提交
28

朔-望's avatar
朔-望 已提交
29 30
namespace paddle_mobile {

朔-望's avatar
朔-望 已提交
31
void ReadBinaryFile(const std::string &filename, std::string *contents) {
32
  std::ifstream fin(filename, std::ios::in | std::ios::binary);
L
liuruilong 已提交
33 34
  PADDLE_MOBILE_ENFORCE(fin.is_open(), "open file: %s failed",
                        filename.c_str());
35 36 37 38 39 40
  fin.seekg(0, std::ios::end);
  contents->clear();
  contents->resize(fin.tellg());
  fin.seekg(0, std::ios::beg);
  fin.read(&(contents->at(0)), contents->size());
  fin.close();
朔-望's avatar
朔-望 已提交
41 42
}

L
liuruilong 已提交
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
static size_t ReadBuffer (const char *file_name, uint8_t **out) {
  printf("%s \n", file_name);
  FILE *fp;
  fp = fopen(file_name, "rb");
  PADDLE_MOBILE_ENFORCE(fp != NULL, "open failed !");

  fseek(fp, 0, SEEK_END);
  size_t size = ftell(fp);
  rewind(fp);

  DLOG << "model size: " << size;

  *out = (uint8_t *)malloc(size);

  size_t cur_len = 0;
  size_t nread;
  while ((nread=fread(*out + cur_len, 1, size - cur_len, fp)) != 0) {
    cur_len += nread;
  }
  fclose(fp);
  return cur_len;
}

朔-望's avatar
朔-望 已提交
66
template <typename Dtype, Precision P>
L
liuruilong 已提交
67
void Loader<Dtype, P>::LoadVar(framework::Variable *variable, const framework::VarDesc &var_desc,
朔-望's avatar
朔-望 已提交
68
                               const std::string &file_path) {
L
liuruilong 已提交
69
  auto tensor = variable->GetMutable<framework::LoDTensor>();
70
  std::ifstream is(file_path);
L
liuruilong 已提交
71 72
  PADDLE_MOBILE_ENFORCE(is.is_open(), "open file: %s failed",
                        file_path.c_str());
L
liuruilong 已提交
73

朔-望's avatar
朔-望 已提交
74 75
  std::fpos<mbstate_t> pos;
  pos = is.tellg();  // save   current   position
76
  is.seekg(0, std::ios::end);
朔-望's avatar
朔-望 已提交
77
  is.seekg(pos);  // restore   saved   position
78 79 80 81 82 83 84 85 86 87 88 89

  // 1. version
  uint32_t version;
  is.read(reinterpret_cast<char *>(&version), sizeof(version));

  // 2 Lod information
  uint64_t lod_level;
  is.read(reinterpret_cast<char *>(&lod_level), sizeof(lod_level));
  auto &lod = *tensor->mutable_lod();
  lod.resize(lod_level);
  for (uint64_t i = 0; i < lod_level; ++i) {
    uint64_t size;
朔-望's avatar
朔-望 已提交
90
    is.read(reinterpret_cast<char *>(&size), sizeof(size));
91 92 93
    std::vector<size_t> tmp(size / sizeof(size_t));
    is.read(reinterpret_cast<char *>(tmp.data()),
            static_cast<std::streamsize>(size));
朔-望's avatar
朔-望 已提交
94 95
    for (auto j : tmp) {
      LOG(kLOG_DEBUG1) << "    lod - " << j;
朔-望's avatar
朔-望 已提交
96
    }
97 98 99 100 101 102 103 104 105 106 107 108 109
    lod[i] = tmp;
  }

  // 3. tensor version
  uint32_t tensor_version;
  is.read(reinterpret_cast<char *>(&tensor_version), sizeof(tensor_version));

  // 4. tensor desc
  int32_t size;
  is.read(reinterpret_cast<char *>(&size), sizeof(size));
  std::unique_ptr<char[]> buf(new char[size]);
  is.read(reinterpret_cast<char *>(buf.get()), size);

L
liuruilong 已提交
110 111
  const framework::TensorDesc &desc = var_desc.Tensor_desc();

L
liuruilong 已提交
112 113 114 115 116 117 118 119

  PaddleMobile__Framework__Proto__VarType__TensorDesc *tensor_desc = NULL;
//  void *v;
//  PaddleMobile__Framework__Proto__VarType__TensorDesc_Closure()(tensor_desc, buf.get());

//  DLOG << "PaddleMobile__Framework__Proto__VarType__TensorDesc_Closure- " << tensor_desc;


L
liuruilong 已提交
120 121 122 123 124 125 126 127
//  framework::TensorDesc &tensor_desc = variable->
//  PaddleMobile__Framework__Proto__ProgramDesc *c_program;
//  uint8_t *proto_buf = NULL;
//  size_t read_size = ReadBuffer(file_path.c_str(), &proto_buf);
//  c_program = paddle_mobile__framework__proto__program_desc__unpack(NULL, read_size, buf);

//  paddle_mobile__framework__proto__var_type__tensor_desc__init()

128 129

  int memory_size = 1;
L
liuruilong 已提交
130
  for (auto l : desc.Dims()) {
朔-望's avatar
朔-望 已提交
131
    memory_size *= l;
132 133
  }

L
liuruilong 已提交
134
  tensor->Resize(framework::make_ddim(desc.Dims()));
135

朔-望's avatar
朔-望 已提交
136
  void *memory = tensor;
137
  int type_size = 0;
L
liuruilong 已提交
138 139
  switch (desc.DataType()) {
    case framework::VARTYPE_TYPE_FP16:
朔-望's avatar
朔-望 已提交
140 141
      type_size = 2;
      break;
L
liuruilong 已提交
142
    case framework::VARTYPE_TYPE_FP32:
朔-望's avatar
朔-望 已提交
143 144 145
      type_size = 4;
      memory = tensor->mutable_data<float>();
      break;
L
liuruilong 已提交
146
    case framework::VARTYPE_TYPE_FP64:
朔-望's avatar
朔-望 已提交
147 148
      type_size = 8;
      break;
L
liuruilong 已提交
149
    case framework::VARTYPE_TYPE_INT32:
朔-望's avatar
朔-望 已提交
150 151
      type_size = 4;
      break;
L
liuruilong 已提交
152
    case framework::VARTYPE_TYPE_INT64:
朔-望's avatar
朔-望 已提交
153 154
      type_size = 8;
      break;
L
liuruilong 已提交
155
    case framework::VARTYPE_TYPE_BOOL:
朔-望's avatar
朔-望 已提交
156 157 158 159
      type_size = 1;
      break;
    default:
      break;
160 161 162 163
  }

  is.read(static_cast<char *>(memory), memory_size * type_size);
  is.close();
朔-望's avatar
朔-望 已提交
164
}
朔-望's avatar
朔-望 已提交
165 166

template <typename Dtype, Precision P>
朔-望's avatar
朔-望 已提交
167 168
const framework::Program<Dtype, P> Loader<Dtype, P>::Load(
    const std::string &dirname) {
169
  std::string model_filename = dirname + "/__model__";
L
liuruilong 已提交
170 171 172 173 174 175 176 177 178 179 180
  PaddleMobile__Framework__Proto__ProgramDesc *c_program;
  uint8_t *buf = NULL;
  size_t read_size = ReadBuffer(model_filename.c_str(), &buf);

  PADDLE_MOBILE_ENFORCE(buf != NULL, "read from __model__ is null");

  c_program = paddle_mobile__framework__proto__program_desc__unpack(NULL, read_size, buf);

  PADDLE_MOBILE_ENFORCE(c_program != NULL, "program is null");

  DLOG << "n_ops: " << (*c_program->blocks)->n_ops;
181 182

  std::shared_ptr<framework::ProgramDesc> originProgramDesc =
L
liuruilong 已提交
183
      std::make_shared<framework::ProgramDesc>(c_program);
184 185

  framework::Program<Dtype, P> program;
L
liuruilong 已提交
186
  program.model_path = dirname;
187 188 189 190 191
  program.originProgram = originProgramDesc;

  std::shared_ptr<framework::Scope> scope =
      std::make_shared<framework::Scope>();
  program.scope = scope;
E
eclipsess 已提交
192 193 194 195 196
  originProgramDesc->Block(0);

  for (const auto &block : originProgramDesc->Blocks()) {
    for (int i = 0; i < block->Vars().size(); ++i) {
      std::shared_ptr<framework::VarDesc> var_desc = block->Vars()[i];
L
liuruilong 已提交
197
//      DLOG << "var name-- " << var_desc->Name();
E
eclipsess 已提交
198
      auto var = scope->Var(var_desc->Name());
L
liuruilong 已提交
199 200

      if (var_desc->Type() == framework::VARTYPE_TYPE_LOD_TENSOR) {
E
eclipsess 已提交
201
        if (var_desc->Persistable() &&
L
liuruilong 已提交
202 203 204 205
            var_desc->Type() != framework::VARTYPE_TYPE_FEED_MINIBATCH &&
            var_desc->Type() != framework::VARTYPE_TYPE_FETCH_LIST) {
//          DLOG << "to load var ";
          LoadVar(var, *var_desc, dirname + "/" + var_desc->Name());
E
eclipsess 已提交
206
        }
L
liuruilong 已提交
207

E
eclipsess 已提交
208 209 210 211 212
      } else {
        // TODO(codeWorm): some.
      }
    }
  }
213

L
liuruilong 已提交
214
  originProgramDesc->Description("program: ");
朔-望's avatar
朔-望 已提交
215

L
liuruilong 已提交
216
  paddle_mobile__framework__proto__program_desc__free_unpacked(c_program, NULL);
217
  return program;
朔-望's avatar
朔-望 已提交
218
}
朔-望's avatar
朔-望 已提交
219

朔-望's avatar
朔-望 已提交
220
template class Loader<CPU, Precision::FP32>;
朔-望's avatar
朔-望 已提交
221

L
liuruilong 已提交
222 223 224 225 226 227 228 229 230 231
#pragma mark - executor

template <typename Dtype, Precision P>
Executor<Dtype, P>::Executor(const framework::Program<Dtype> p) : program_(p) {
  if (use_optimize_) {
    to_predict_program_ = program_.optimizeProgram;
  } else {
    to_predict_program_ = program_.originProgram;
  }

L
liuruilong 已提交
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
  const std::vector<std::shared_ptr<framework::BlockDesc>> blocks =
      to_predict_program_->Blocks();
  for (int i = 0; i < blocks.size(); ++i) {
    std::shared_ptr<framework::BlockDesc> block_desc = blocks[i];
    std::vector<std::shared_ptr<framework::OpDesc>> ops = block_desc->Ops();
    for (int j = 0; j < ops.size(); ++j) {
      std::shared_ptr<framework::OpDesc> op = ops[j];
      //              auto op_base =
      //              framework::OpRegistry<Dtype>::CreateOp(op->Type(),
      //                      op->GetInputs(), op->GetOutputs(),
      //                      op->GetAttrMap(), program_.scope);
      //              op_base->InferShape();
    }
  }
  InitMemory();
L
liuruilong 已提交
247 248 249
}

template <typename Dtype, Precision P>
L
liuruilong 已提交
250
void Executor<Dtype, P>::LoadMemory(const framework::VarDesc var_desc, framework::LoDTensor *tensor,
L
liuruilong 已提交
251
                                    const std::string &file_path) {
L
liuruilong 已提交
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
  std::ifstream is(file_path);
  PADDLE_MOBILE_ENFORCE(is.is_open(), "open file: %s failed",
                        file_path.c_str());
  std::fpos<mbstate_t> pos;
  pos = is.tellg();  // save   current   position
  is.seekg(0, std::ios::end);
  is.seekg(pos);  // restore   saved   position

  // 1. version
  uint32_t version;
  is.read(reinterpret_cast<char *>(&version), sizeof(version));

  // 2 Lod information
  uint64_t lod_level;
  is.read(reinterpret_cast<char *>(&lod_level), sizeof(lod_level));
  auto &lod = *tensor->mutable_lod();
  lod.resize(lod_level);
  for (uint64_t i = 0; i < lod_level; ++i) {
    uint64_t size;
    is.read(reinterpret_cast<char *>(&size), sizeof(size));
    std::vector<size_t> tmp(size / sizeof(size_t));
    is.read(reinterpret_cast<char *>(tmp.data()),
            static_cast<std::streamsize>(size));
    for (auto j : tmp) {
      LOG(kLOG_DEBUG1) << "    lod - " << j;
    }
    lod[i] = tmp;
  }

  // 3. tensor version
  uint32_t tensor_version;
  is.read(reinterpret_cast<char *>(&tensor_version), sizeof(tensor_version));

  // 4. tensor desc
  int32_t size;
  is.read(reinterpret_cast<char *>(&size), sizeof(size));
  std::unique_ptr<char[]> buf(new char[size]);
  is.read(reinterpret_cast<char *>(buf.get()), size);

L
liuruilong 已提交
291 292
  const framework::TensorDesc &desc = var_desc.Tensor_desc();

L
liuruilong 已提交
293 294

  int memory_size = 1;
L
liuruilong 已提交
295
  for (auto l : desc.Dims()) {
L
liuruilong 已提交
296 297 298
    memory_size *= l;
  }

L
liuruilong 已提交
299
  tensor->Resize(framework::make_ddim(desc.Dims()));
L
liuruilong 已提交
300 301 302

  void *memory = tensor;
  int type_size = 0;
L
liuruilong 已提交
303 304
  switch (desc.DataType()) {
    case framework::VARTYPE_TYPE_FP16:
L
liuruilong 已提交
305 306
      type_size = 2;
      break;
L
liuruilong 已提交
307
    case framework::VARTYPE_TYPE_FP32:
L
liuruilong 已提交
308 309 310
      type_size = 4;
      memory = tensor->mutable_data<float>();
      break;
L
liuruilong 已提交
311
    case framework::VARTYPE_TYPE_FP64:
L
liuruilong 已提交
312 313
      type_size = 8;
      break;
L
liuruilong 已提交
314
    case framework::VARTYPE_TYPE_INT32:
L
liuruilong 已提交
315 316
      type_size = 4;
      break;
L
liuruilong 已提交
317
    case framework::VARTYPE_TYPE_INT64:
L
liuruilong 已提交
318 319
      type_size = 8;
      break;
L
liuruilong 已提交
320
    case framework::VARTYPE_TYPE_BOOL:
L
liuruilong 已提交
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
      type_size = 1;
      break;
    default:
      break;
  }

  is.read(static_cast<char *>(memory), memory_size * type_size);
  is.close();
};

template <typename Dtype, Precision P>
void Executor<Dtype, P>::InitMemory() {
  for (const auto &block : to_predict_program_->Blocks()) {
    for (const auto &var_desc : block->Vars()) {
      auto var = program_.scope->Var(var_desc->Name());
L
liuruilong 已提交
336 337
      if (var_desc->Persistable()) {
        auto tensor = var->template GetMutable<framework::LoDTensor>();
L
liuruilong 已提交
338
        LoadMemory(*var_desc, tensor, program_.model_path + "/" + var_desc->Name());
L
liuruilong 已提交
339
      } else {
L
liuruilong 已提交
340
        if (var_desc->Type() == framework::VARTYPE_TYPE_LOD_TENSOR) {
L
liuruilong 已提交
341 342 343 344
          auto tensor = var->template GetMutable<framework::Tensor>();
          tensor->template mutable_data<Ptype>();
        }
      }
L
liuruilong 已提交
345 346 347 348 349
    }
  }
}

template <typename Dtype, Precision P>
L
liuruilong 已提交
350 351
std::shared_ptr<framework::Tensor> Executor<Dtype, P>::predict(
    framework::Tensor &t) {
L
liuruilong 已提交
352 353 354 355 356 357 358
  // feed
  auto scope = program_.scope;
  framework::Variable *g_feed_value = scope->Var("pixel");
  auto tensor = g_feed_value->GetMutable<framework::Tensor>();
  tensor->ShareDataWith(t);

  framework::Variable *con_output = scope->Var("conv2d_0.tmp_0");
L
liuruilong 已提交
359 360
  framework::Tensor *output_tensor =
      con_output->GetMutable<framework::Tensor>();
L
liuruilong 已提交
361 362 363 364 365
  output_tensor->mutable_data<float>({1, 16, 32, 32});
  //  std::cout << typeid(output_tensor).name() << std::endl;
  //  std::cout << "output_tensor dims: " << output_tensor->dims() <<
  //  std::endl;

L
liuruilong 已提交
366 367
  std::shared_ptr<framework::Tensor> out_tensor =
      std::make_shared<framework::LoDTensor>();
L
liuruilong 已提交
368 369 370 371 372 373 374 375
  out_tensor.reset(output_tensor);

  predict(t, 0);
  return out_tensor;
}

template <typename Dtype, Precision P>
void Executor<Dtype, P>::predict(const framework::Tensor &t, int block_id) {
L
liuruilong 已提交
376 377 378
  //  framework::Variable *g_feed_value = program_.scope->Var("feed");
  //  auto feed_tensor = g_feed_value->GetMutable<framework::Tensor>();
  //  feed_tensor->ShareDataWith(t);
L
liuruilong 已提交
379 380

  std::shared_ptr<framework::BlockDesc> to_predict_block =
L
liuruilong 已提交
381
      to_predict_program_->Block(block_id);
L
liuruilong 已提交
382 383 384 385 386 387 388
  for (int j = 0; j < ops_of_block_[*to_predict_block.get()].size(); ++j) {
    auto op = ops_of_block_[*to_predict_block.get()][j];
    op->Run();
  }
}

template <typename Dtype, Precision P>
L
liuruilong 已提交
389 390
std::vector<typename Executor<Dtype, P>::Ptype> Executor<Dtype, P>::predict(
    const std::vector<Ptype> &input, const std::vector<int64_t> &dims) {
L
liuruilong 已提交
391 392 393 394 395
  DLOG << "start predict: ";

  framework::Tensor tensor;
  auto ddim = framework::make_ddim(dims);

L
liuruilong 已提交
396
  auto input_ptr = tensor.mutable_data<Ptype>(ddim);
L
liuruilong 已提交
397 398 399 400 401 402 403 404 405 406 407 408 409 410
  for (int i = 0; i < input.size(); ++i) {
    input_ptr[i] = input[i];
  }

  predict(tensor, 0);

  framework::Variable *g_feed_value = program_.scope->Var("col");
  auto feed_tensor = g_feed_value->GetMutable<framework::Tensor>();

  return {};
}

template class Executor<CPU, Precision::FP32>;

朔-望's avatar
朔-望 已提交
411
}  // namespace paddle_mobile