general_model.cpp 17.7 KB
Newer Older
G
guru4elephant 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// 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.

G
guru4elephant 已提交
15
#include "core/general-client/include/general_model.h"
M
MRXLT 已提交
16
#include <fstream>
G
guru4elephant 已提交
17 18 19
#include "core/sdk-cpp/builtin_format.pb.h"
#include "core/sdk-cpp/include/common.h"
#include "core/sdk-cpp/include/predictor_sdk.h"
G
guru4elephant 已提交
20
#include "core/util/include/timer.h"
G
guru4elephant 已提交
21

22 23 24
DEFINE_bool(profile_client, false, "");
DEFINE_bool(profile_server, false, "");

G
guru4elephant 已提交
25
using baidu::paddle_serving::Timer;
G
guru4elephant 已提交
26 27 28 29 30
using baidu::paddle_serving::predictor::general_model::Request;
using baidu::paddle_serving::predictor::general_model::Response;
using baidu::paddle_serving::predictor::general_model::Tensor;
using baidu::paddle_serving::predictor::general_model::FeedInst;
using baidu::paddle_serving::predictor::general_model::FetchInst;
H
HexToString 已提交
31
enum ProtoDataType { P_INT64, P_FLOAT32, P_INT32, P_STRING };
32
std::once_flag gflags_init_flag;
M
MRXLT 已提交
33
namespace py = pybind11;
34

G
guru4elephant 已提交
35 36 37
namespace baidu {
namespace paddle_serving {
namespace general_model {
38
using configure::GeneralModelConfig;
G
guru4elephant 已提交
39

40 41
void PredictorClient::init_gflags(std::vector<std::string> argv) {
  std::call_once(gflags_init_flag, [&]() {
42
#ifndef BCLOUD
M
MRXLT 已提交
43
    FLAGS_logtostderr = true;
44
#endif
M
MRXLT 已提交
45 46 47 48 49 50 51 52 53 54 55 56
    argv.insert(argv.begin(), "dummy");
    int argc = argv.size();
    char **arr = new char *[argv.size()];
    std::string line;
    for (size_t i = 0; i < argv.size(); i++) {
      arr[i] = &argv[i][0];
      line += argv[i];
      line += ' ';
    }
    google::ParseCommandLineFlags(&argc, &arr, true);
    VLOG(2) << "Init commandline: " << line;
  });
57 58
}

H
HexToString 已提交
59
int PredictorClient::init(const std::vector<std::string> &conf_file) {
60 61
  try {
    GeneralModelConfig model_config;
H
HexToString 已提交
62
    if (configure::read_proto_conf(conf_file[0].c_str(), &model_config) != 0) {
63
      LOG(ERROR) << "Failed to load general model config"
H
HexToString 已提交
64
                 << ", file path: " << conf_file[0];
65 66
      return -1;
    }
H
HexToString 已提交
67
    
68 69 70 71
    _feed_name_to_idx.clear();
    _fetch_name_to_idx.clear();
    _shape.clear();
    int feed_var_num = model_config.feed_var_size();
H
HexToString 已提交
72
    VLOG(2) << "feed var num: " << feed_var_num;
73 74
    for (int i = 0; i < feed_var_num; ++i) {
      _feed_name_to_idx[model_config.feed_var(i).alias_name()] = i;
75 76
      VLOG(2) << "feed alias name: " << model_config.feed_var(i).alias_name()
              << " index: " << i;
77
      std::vector<int> tmp_feed_shape;
M
MRXLT 已提交
78 79
      VLOG(2) << "feed"
              << "[" << i << "] shape:";
80 81
      for (int j = 0; j < model_config.feed_var(i).shape_size(); ++j) {
        tmp_feed_shape.push_back(model_config.feed_var(i).shape(j));
M
MRXLT 已提交
82
        VLOG(2) << "shape[" << j << "]: " << model_config.feed_var(i).shape(j);
83 84
      }
      _type.push_back(model_config.feed_var(i).feed_type());
M
MRXLT 已提交
85 86 87
      VLOG(2) << "feed"
              << "[" << i
              << "] feed type: " << model_config.feed_var(i).feed_type();
88
      _shape.push_back(tmp_feed_shape);
G
guru4elephant 已提交
89 90
    }

H
HexToString 已提交
91 92 93 94 95 96 97 98 99 100
    if (conf_file.size()>1) {
      model_config.Clear();
      if (configure::read_proto_conf(conf_file[conf_file.size()-1].c_str(), &model_config) != 0) {
        LOG(ERROR) << "Failed to load general model config"
                  << ", file path: " << conf_file[conf_file.size()-1];
        return -1;
      }
    }
    int fetch_var_num = model_config.fetch_var_size();
    VLOG(2) << "fetch_var_num: " << fetch_var_num;
101 102
    for (int i = 0; i < fetch_var_num; ++i) {
      _fetch_name_to_idx[model_config.fetch_var(i).alias_name()] = i;
M
MRXLT 已提交
103 104
      VLOG(2) << "fetch [" << i << "]"
              << " alias name: " << model_config.fetch_var(i).alias_name();
105 106
      _fetch_name_to_var_name[model_config.fetch_var(i).alias_name()] =
          model_config.fetch_var(i).name();
107 108
      _fetch_name_to_type[model_config.fetch_var(i).alias_name()] =
          model_config.fetch_var(i).fetch_type();
109
    }
M
MRXLT 已提交
110
  } catch (std::exception &e) {
111 112
    LOG(ERROR) << "Failed load general model config" << e.what();
    return -1;
G
guru4elephant 已提交
113
  }
114
  return 0;
G
guru4elephant 已提交
115 116
}

M
MRXLT 已提交
117 118
void PredictorClient::set_predictor_conf(const std::string &conf_path,
                                         const std::string &conf_file) {
G
guru4elephant 已提交
119 120 121
  _predictor_path = conf_path;
  _predictor_conf = conf_file;
}
122 123 124
int PredictorClient::destroy_predictor() {
  _api.thrd_finalize();
  _api.destroy();
B
barrierye 已提交
125
  return 0;
126 127
}

M
MRXLT 已提交
128
int PredictorClient::create_predictor_by_desc(const std::string &sdk_desc) {
G
guru4elephant 已提交
129 130 131 132
  if (_api.create(sdk_desc) != 0) {
    LOG(ERROR) << "Predictor Creation Failed";
    return -1;
  }
D
dongdaxiang 已提交
133
  // _api.thrd_initialize();
B
barrierye 已提交
134
  return 0;
G
guru4elephant 已提交
135 136
}

G
guru4elephant 已提交
137
int PredictorClient::create_predictor() {
G
guru4elephant 已提交
138 139
  VLOG(2) << "Predictor path: " << _predictor_path
          << " predictor file: " << _predictor_conf;
G
guru4elephant 已提交
140 141 142 143
  if (_api.create(_predictor_path.c_str(), _predictor_conf.c_str()) != 0) {
    LOG(ERROR) << "Predictor Creation Failed";
    return -1;
  }
D
dongdaxiang 已提交
144
  // _api.thrd_initialize();
B
barrierye 已提交
145
  return 0;
G
guru4elephant 已提交
146 147
}

M
MRXLT 已提交
148 149 150 151
int PredictorClient::numpy_predict(
    const std::vector<std::vector<py::array_t<float>>> &float_feed_batch,
    const std::vector<std::string> &float_feed_name,
    const std::vector<std::vector<int>> &float_shape,
W
wangjiawei04 已提交
152
    const std::vector<std::vector<int>> &float_lod_slot_batch,
M
MRXLT 已提交
153 154 155
    const std::vector<std::vector<py::array_t<int64_t>>> &int_feed_batch,
    const std::vector<std::string> &int_feed_name,
    const std::vector<std::vector<int>> &int_shape,
W
wangjiawei04 已提交
156
    const std::vector<std::vector<int>> &int_lod_slot_batch,
H
HexToString 已提交
157 158 159 160
    const std::vector<std::vector<std::string>>& string_feed_batch,
    const std::vector<std::string>& string_feed_name,
    const std::vector<std::vector<int>>& string_shape,
    const std::vector<std::vector<int>>& string_lod_slot_batch,
M
MRXLT 已提交
161 162
    const std::vector<std::string> &fetch_name,
    PredictorRes &predict_res_batch,
163 164
    const int &pid,
    const uint64_t log_id) {
H
HexToString 已提交
165 166
  int batch_size = std::max( float_feed_batch.size(), int_feed_batch.size() );
  batch_size = batch_size>string_feed_batch.size()? batch_size : string_feed_batch.size();
D
dongdaxiang 已提交
167
  VLOG(2) << "batch size: " << batch_size;
M
MRXLT 已提交
168 169 170 171 172 173 174 175 176 177 178 179 180
  predict_res_batch.clear();
  Timer timeline;
  int64_t preprocess_start = timeline.TimeStampUS();

  int fetch_name_num = fetch_name.size();

  _api.thrd_initialize();
  std::string variant_tag;
  _predictor = _api.fetch_predictor("general_model", &variant_tag);
  predict_res_batch.set_variant_tag(variant_tag);
  VLOG(2) << "fetch general model predictor done.";
  VLOG(2) << "float feed name size: " << float_feed_name.size();
  VLOG(2) << "int feed name size: " << int_feed_name.size();
H
HexToString 已提交
181
  VLOG(2) << "string feed name size: " << string_feed_name.size();
M
MRXLT 已提交
182 183
  VLOG(2) << "max body size : " << brpc::fLU64::FLAGS_max_body_size;
  Request req;
184
  req.set_log_id(log_id);
M
MRXLT 已提交
185 186 187 188 189 190 191 192 193 194
  for (auto &name : fetch_name) {
    req.add_fetch_var_names(name);
  }

  for (int bi = 0; bi < batch_size; bi++) {
    VLOG(2) << "prepare batch " << bi;
    std::vector<Tensor *> tensor_vec;
    FeedInst *inst = req.add_insts();
    std::vector<py::array_t<float>> float_feed = float_feed_batch[bi];
    std::vector<py::array_t<int64_t>> int_feed = int_feed_batch[bi];
H
HexToString 已提交
195
    std::vector<std::string> string_feed = string_feed_batch[bi];
M
MRXLT 已提交
196 197 198 199 200 201 202 203
    for (auto &name : float_feed_name) {
      tensor_vec.push_back(inst->add_tensor_array());
    }

    for (auto &name : int_feed_name) {
      tensor_vec.push_back(inst->add_tensor_array());
    }

H
HexToString 已提交
204 205 206 207 208
    for (auto &name : string_feed_name) {
      tensor_vec.push_back(inst->add_tensor_array());
    }

    VLOG(2) << "batch [" << bi << "] " << "prepared";
M
MRXLT 已提交
209 210 211 212 213 214 215 216 217 218

    int vec_idx = 0;
    for (auto &name : float_feed_name) {
      int idx = _feed_name_to_idx[name];
      Tensor *tensor = tensor_vec[idx];
      VLOG(2) << "prepare float feed " << name << " shape size "
              << float_shape[vec_idx].size();
      for (uint32_t j = 0; j < float_shape[vec_idx].size(); ++j) {
        tensor->add_shape(float_shape[vec_idx][j]);
      }
W
wangjiawei04 已提交
219 220 221
      for (uint32_t j = 0; j < float_lod_slot_batch[vec_idx].size(); ++j) {
        tensor->add_lod(float_lod_slot_batch[vec_idx][j]);
      }
H
HexToString 已提交
222
      tensor->set_elem_type(P_FLOAT32);
M
MRXLT 已提交
223 224
      const int float_shape_size = float_shape[vec_idx].size();
      switch (float_shape_size) {
M
bug fix  
MRXLT 已提交
225 226 227 228 229 230 231 232 233 234 235 236 237
        case 4: {
          auto float_array = float_feed[vec_idx].unchecked<4>();
          for (ssize_t i = 0; i < float_array.shape(0); i++) {
            for (ssize_t j = 0; j < float_array.shape(1); j++) {
              for (ssize_t k = 0; k < float_array.shape(2); k++) {
                for (ssize_t l = 0; l < float_array.shape(3); l++) {
                  tensor->add_float_data(float_array(i, j, k, l));
                }
              }
            }
          }
          break;
        }
M
MRXLT 已提交
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
        case 3: {
          auto float_array = float_feed[vec_idx].unchecked<3>();
          for (ssize_t i = 0; i < float_array.shape(0); i++) {
            for (ssize_t j = 0; j < float_array.shape(1); j++) {
              for (ssize_t k = 0; k < float_array.shape(2); k++) {
                tensor->add_float_data(float_array(i, j, k));
              }
            }
          }
          break;
        }
        case 2: {
          auto float_array = float_feed[vec_idx].unchecked<2>();
          for (ssize_t i = 0; i < float_array.shape(0); i++) {
            for (ssize_t j = 0; j < float_array.shape(1); j++) {
              tensor->add_float_data(float_array(i, j));
            }
          }
          break;
        }
M
bug fix  
MRXLT 已提交
258 259 260 261 262 263 264
        case 1: {
          auto float_array = float_feed[vec_idx].unchecked<1>();
          for (ssize_t i = 0; i < float_array.shape(0); i++) {
            tensor->add_float_data(float_array(i));
          }
          break;
        }
M
MRXLT 已提交
265 266 267
      }
      vec_idx++;
    }
H
HexToString 已提交
268
    
M
MRXLT 已提交
269 270 271 272 273 274 275
    VLOG(2) << "batch [" << bi << "] "
            << "float feed value prepared";

    vec_idx = 0;
    for (auto &name : int_feed_name) {
      int idx = _feed_name_to_idx[name];
      Tensor *tensor = tensor_vec[idx];
M
MRXLT 已提交
276

M
MRXLT 已提交
277 278 279
      for (uint32_t j = 0; j < int_shape[vec_idx].size(); ++j) {
        tensor->add_shape(int_shape[vec_idx][j]);
      }
W
wangjiawei04 已提交
280 281 282
      for (uint32_t j = 0; j < int_lod_slot_batch[vec_idx].size(); ++j) {
        tensor->add_lod(int_lod_slot_batch[vec_idx][j]);
      }
M
MRXLT 已提交
283 284
      tensor->set_elem_type(_type[idx]);

H
HexToString 已提交
285
      if (_type[idx] == P_INT64) {
M
MRXLT 已提交
286 287 288 289 290 291
        VLOG(2) << "prepare int feed " << name << " shape size "
                << int_shape[vec_idx].size();
      } else {
        VLOG(2) << "prepare int32 feed " << name << " shape size "
                << int_shape[vec_idx].size();
      }
M
MRXLT 已提交
292 293 294 295

      const int int_shape_size = int_shape[vec_idx].size();
      switch (int_shape_size) {
        case 4: {
M
bug fix  
MRXLT 已提交
296
          auto int_array = int_feed[vec_idx].unchecked<4>();
M
MRXLT 已提交
297 298 299 300
          for (ssize_t i = 0; i < int_array.shape(0); i++) {
            for (ssize_t j = 0; j < int_array.shape(1); j++) {
              for (ssize_t k = 0; k < int_array.shape(2); k++) {
                for (ssize_t l = 0; k < int_array.shape(3); l++) {
H
HexToString 已提交
301
                  if (_type[idx] == P_INT64) {
M
MRXLT 已提交
302 303 304 305
                    tensor->add_int64_data(int_array(i, j, k, l));
                  } else {
                    tensor->add_int_data(int_array(i, j, k, l));
                  }
M
MRXLT 已提交
306 307 308 309 310 311 312 313 314 315 316
                }
              }
            }
          }
          break;
        }
        case 3: {
          auto int_array = int_feed[vec_idx].unchecked<3>();
          for (ssize_t i = 0; i < int_array.shape(0); i++) {
            for (ssize_t j = 0; j < int_array.shape(1); j++) {
              for (ssize_t k = 0; k < int_array.shape(2); k++) {
H
HexToString 已提交
317
                if (_type[idx] == P_INT64) {
M
MRXLT 已提交
318 319 320 321
                  tensor->add_int64_data(int_array(i, j, k));
                } else {
                  tensor->add_int_data(int_array(i, j, k));
                }
M
MRXLT 已提交
322 323 324 325 326 327 328 329 330
              }
            }
          }
          break;
        }
        case 2: {
          auto int_array = int_feed[vec_idx].unchecked<2>();
          for (ssize_t i = 0; i < int_array.shape(0); i++) {
            for (ssize_t j = 0; j < int_array.shape(1); j++) {
H
HexToString 已提交
331
              if (_type[idx] == P_INT64) {
M
MRXLT 已提交
332 333 334 335
                tensor->add_int64_data(int_array(i, j));
              } else {
                tensor->add_int_data(int_array(i, j));
              }
M
MRXLT 已提交
336 337 338 339 340
            }
          }
          break;
        }
        case 1: {
M
bug fix  
MRXLT 已提交
341
          auto int_array = int_feed[vec_idx].unchecked<1>();
M
MRXLT 已提交
342
          for (ssize_t i = 0; i < int_array.shape(0); i++) {
H
HexToString 已提交
343
            if (_type[idx] == P_INT64) {
M
MRXLT 已提交
344 345 346 347
              tensor->add_int64_data(int_array(i));
            } else {
              tensor->add_int_data(int_array(i));
            }
M
MRXLT 已提交
348 349 350 351 352 353 354 355 356
          }
          break;
        }
      }
      vec_idx++;
    }

    VLOG(2) << "batch [" << bi << "] "
            << "int feed value prepared";
H
HexToString 已提交
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388

    vec_idx = 0;
    for (auto &name : string_feed_name) {
      int idx = _feed_name_to_idx[name];
      Tensor *tensor = tensor_vec[idx];

      for (uint32_t j = 0; j < string_shape[vec_idx].size(); ++j) {
        tensor->add_shape(string_shape[vec_idx][j]);
      }
      for (uint32_t j = 0; j < string_lod_slot_batch[vec_idx].size(); ++j) {
        tensor->add_lod(string_lod_slot_batch[vec_idx][j]);
      }
      tensor->set_elem_type(P_STRING);

      const int string_shape_size = string_shape[vec_idx].size();
      //string_shape[vec_idx] = [1];cause numpy has no datatype of string.
      //we pass string via vector<vector<string> >.
      if( string_shape_size!= 1 ){
        LOG(ERROR) << "string_shape_size should be 1-D, but received is : " << string_shape_size;
        return -1;
      }
      switch (string_shape_size) {
        case 1: {
          tensor->add_data(string_feed[vec_idx]);
          break;
        }
      }
      vec_idx++;
    }
    
    VLOG(2) << "batch [" << bi << "] "
            << "string feed value prepared";
M
MRXLT 已提交
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
  }

  int64_t preprocess_end = timeline.TimeStampUS();

  int64_t client_infer_start = timeline.TimeStampUS();

  Response res;

  int64_t client_infer_end = 0;
  int64_t postprocess_start = 0;
  int64_t postprocess_end = 0;

  if (FLAGS_profile_client) {
    if (FLAGS_profile_server) {
      req.set_profile_server(true);
    }
  }

  res.Clear();
  if (_predictor->inference(&req, &res) != 0) {
    LOG(ERROR) << "failed call predictor with req: " << req.ShortDebugString();
    return -1;
  } else {
    client_infer_end = timeline.TimeStampUS();
    postprocess_start = client_infer_end;
    VLOG(2) << "get model output num";
    uint32_t model_num = res.outputs_size();
    VLOG(2) << "model num: " << model_num;
B
barrierye 已提交
417 418 419
    for (uint32_t m_idx = 0; m_idx < model_num; ++m_idx) {
      VLOG(2) << "process model output index: " << m_idx;
      auto output = res.outputs(m_idx);
B
barrierye 已提交
420 421
      ModelRes model;
      model.set_engine_name(output.engine_name());
B
barrierye 已提交
422

M
MRXLT 已提交
423
      int idx = 0;
M
MRXLT 已提交
424
      for (auto &name : fetch_name) {
B
barrierye 已提交
425
        // int idx = _fetch_name_to_idx[name];
B
barrierye 已提交
426
        int shape_size = output.insts(0).tensor_array(idx).shape_size();
B
barrierye 已提交
427 428
        VLOG(2) << "fetch var " << name << " index " << idx << " shape size "
                << shape_size;
B
barrierye 已提交
429 430 431 432 433 434 435 436 437 438 439
        model._shape_map[name].resize(shape_size);
        for (int i = 0; i < shape_size; ++i) {
          model._shape_map[name][i] =
              output.insts(0).tensor_array(idx).shape(i);
        }
        int lod_size = output.insts(0).tensor_array(idx).lod_size();
        if (lod_size > 0) {
          model._lod_map[name].resize(lod_size);
          for (int i = 0; i < lod_size; ++i) {
            model._lod_map[name][i] = output.insts(0).tensor_array(idx).lod(i);
          }
440
        }
B
barrierye 已提交
441
        idx += 1;
B
barrierye 已提交
442
      }
443

M
MRXLT 已提交
444 445
      idx = 0;

B
barrierye 已提交
446
      for (auto &name : fetch_name) {
B
barrierye 已提交
447
        // int idx = _fetch_name_to_idx[name];
H
HexToString 已提交
448
        if (_fetch_name_to_type[name] == P_INT64) {
M
MRXLT 已提交
449
          VLOG(2) << "ferch var " << name << "type int64";
B
barrierye 已提交
450
          int size = output.insts(0).tensor_array(idx).int64_data_size();
W
WangXi 已提交
451 452 453
          model._int64_value_map[name] = std::vector<int64_t>(
              output.insts(0).tensor_array(idx).int64_data().begin(),
              output.insts(0).tensor_array(idx).int64_data().begin() + size);
H
HexToString 已提交
454
        } else if (_fetch_name_to_type[name] == P_FLOAT32) {
B
barrierye 已提交
455
          VLOG(2) << "fetch var " << name << "type float";
B
barrierye 已提交
456
          int size = output.insts(0).tensor_array(idx).float_data_size();
W
WangXi 已提交
457 458 459
          model._float_value_map[name] = std::vector<float>(
              output.insts(0).tensor_array(idx).float_data().begin(),
              output.insts(0).tensor_array(idx).float_data().begin() + size);
H
HexToString 已提交
460
        } else if (_fetch_name_to_type[name] == P_INT32) {
M
MRXLT 已提交
461 462
          VLOG(2) << "fetch var " << name << "type int32";
          int size = output.insts(0).tensor_array(idx).int_data_size();
M
MRXLT 已提交
463 464 465
          model._int32_value_map[name] = std::vector<int32_t>(
              output.insts(0).tensor_array(idx).int_data().begin(),
              output.insts(0).tensor_array(idx).int_data().begin() + size);
M
MRXLT 已提交
466
        }
B
barrierye 已提交
467
        idx += 1;
M
MRXLT 已提交
468
      }
B
barrierye 已提交
469
      predict_res_batch.add_model_res(std::move(model));
M
MRXLT 已提交
470
    }
471
    postprocess_end = timeline.TimeStampUS();
M
MRXLT 已提交
472 473
  }

M
MRXLT 已提交
474 475 476
  if (FLAGS_profile_client) {
    std::ostringstream oss;
    oss << "PROFILE\t"
M
MRXLT 已提交
477
        << "pid:" << pid << "\t"
M
MRXLT 已提交
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
        << "prepro_0:" << preprocess_start << " "
        << "prepro_1:" << preprocess_end << " "
        << "client_infer_0:" << client_infer_start << " "
        << "client_infer_1:" << client_infer_end << " ";
    if (FLAGS_profile_server) {
      int op_num = res.profile_time_size() / 2;
      for (int i = 0; i < op_num; ++i) {
        oss << "op" << i << "_0:" << res.profile_time(i * 2) << " ";
        oss << "op" << i << "_1:" << res.profile_time(i * 2 + 1) << " ";
      }
    }

    oss << "postpro_0:" << postprocess_start << " ";
    oss << "postpro_1:" << postprocess_end;

    fprintf(stderr, "%s\n", oss.str().c_str());
  }
D
dongdaxiang 已提交
495 496

  _api.thrd_clear();
M
MRXLT 已提交
497
  return 0;
M
MRXLT 已提交
498
}
G
guru4elephant 已提交
499 500 501
}  // namespace general_model
}  // namespace paddle_serving
}  // namespace baidu