chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:40:42 +08:00
commit e25996e7db
15472 changed files with 3536181 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,60 @@
/* Copyright (c) 2020 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 <fstream>
#include <iostream>
#include "paddle/fluid/inference/api/paddle_analysis_config.h"
#include "paddle/phi/backends/cpu/cpu_info.h"
#include "test/cpp/inference/api/tester_helper.h"
PD_DEFINE_bool(enable_onednn, true, "Enable ONEDNN");
namespace paddle {
namespace inference {
namespace analysis {
void SetConfig(AnalysisConfig *cfg) {
std::ifstream model_file(FLAGS_infer_model + "/__model__");
if (model_file.good())
cfg->SetModel(FLAGS_infer_model);
else
cfg->SetModel(FLAGS_infer_model + "/inference.pdmodel",
FLAGS_infer_model + "/inference.pdiparams");
cfg->DisableGpu();
cfg->SwitchIrOptim();
cfg->SwitchSpecifyInputNames();
cfg->SetCpuMathLibraryNumThreads(FLAGS_num_threads);
if (!FLAGS_enable_onednn) cfg->DisableONEDNN();
}
TEST(Analyzer_bfloat16_image_classification, bfloat16) {
AnalysisConfig cfg;
SetConfig(&cfg);
AnalysisConfig b_cfg;
SetConfig(&b_cfg);
// read data from file and prepare batches with test data
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInputs(&input_slots_all);
if (FLAGS_enable_onednn && FLAGS_enable_bf16 &&
phi::backends::cpu::MayIUse(phi::backends::cpu::cpu_isa_t::avx512_bf16)) {
b_cfg.EnableOnednnBfloat16();
} else {
FLAGS_enable_bf16 = false;
}
CompareBFloat16AndAnalysis(&cfg, &b_cfg, input_slots_all);
}
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,183 @@
/* Copyright (c) 2021 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <string>
#include <vector>
#if defined(PADDLE_WITH_CUDA)
#include <cuda_runtime.h>
#endif
#include "paddle/common/flags.h"
#include "paddle/fluid/inference/capi_exp/pd_inference_api.h"
PD_DEFINE_string(infer_model, "", "model path");
namespace paddle {
namespace inference {
namespace analysis {
TEST(PD_Config, gpu_interface) {
std::string model_dir = FLAGS_infer_model + "/mobilenet";
std::string prog_file = model_dir + "/__model__";
std::string param_file = model_dir + "/__params__";
std::string opt_cache_dir = FLAGS_infer_model + "/OptimCacheDir";
const char* ops_name = "conv_2d";
PD_Config* config = PD_ConfigCreate();
PD_ConfigSetModel(config, prog_file.c_str(), param_file.c_str());
PD_ConfigSetOptimCacheDir(config, opt_cache_dir.c_str());
PD_ConfigEnableUseGpu(config, 100, 0, 0);
bool use_gpu = PD_ConfigUseGpu(config);
EXPECT_TRUE(use_gpu);
int init_size = PD_ConfigMemoryPoolInitSizeMb(config);
EXPECT_EQ(init_size, 100);
int gpu_device_id = PD_ConfigGpuDeviceId(config);
EXPECT_EQ(gpu_device_id, 0);
float frac = PD_ConfigFractionOfGpuMemoryForPool(config);
LOG(INFO) << frac;
PD_ConfigEnableCudnn(config);
bool cudnn = PD_ConfigCudnnEnabled(config);
EXPECT_TRUE(cudnn);
PD_ConfigEnableTensorRtEngine(
config, 1 << 20, 1, 3, PD_PRECISION_INT8, FALSE, TRUE);
bool trt_enable = PD_ConfigTensorRtEngineEnabled(config);
EXPECT_TRUE(trt_enable);
const char* tensor_name = "image";
std::array<size_t, 1> shapes_num = {4};
std::array<int32_t, 4> min_shape = {1, 3, 36, 36};
std::array<int32_t, 4> max_shape = {1, 3, 224, 224};
std::array<int32_t, 4> opt_shape = {1, 3, 224, 224};
int32_t* min_shape_ptr = min_shape.data();
int32_t* max_shape_ptr = max_shape.data();
int32_t* opt_shape_ptr = opt_shape.data();
PD_ConfigSetTrtDynamicShapeInfo(config,
1,
&tensor_name,
shapes_num.data(),
&min_shape_ptr,
&max_shape_ptr,
&opt_shape_ptr,
FALSE);
PD_ConfigDisableTensorRtOPs(config, 1, &ops_name);
PD_ConfigEnableVarseqlen(config);
bool oss_enabled = PD_ConfigTensorRtOssEnabled(config);
EXPECT_TRUE(oss_enabled);
PD_ConfigEnableTensorRtDla(config, 4);
bool dla_enabled = PD_ConfigTensorRtDlaEnabled(config);
EXPECT_TRUE(dla_enabled);
PD_ConfigEnableGpuMultiStream(config);
bool thread_local_thread = PD_ConfigThreadLocalStreamEnabled(config);
EXPECT_TRUE(thread_local_thread);
#if defined(PADDLE_WITH_CUDA)
{
cudaStream_t external_stream;
cudaStreamCreate(&external_stream);
PD_ConfigSetExecStream(config, external_stream);
}
#endif
PD_ConfigDisableGpu(config);
PD_ConfigDestroy(config);
}
TEST(PD_Config, use_gpu) {
std::string model_dir = FLAGS_infer_model + "/mobilenet";
PD_Config* config = PD_ConfigCreate();
PD_ConfigDisableGpu(config);
PD_ConfigSetCpuMathLibraryNumThreads(config, 10);
int num_thread = PD_ConfigGetCpuMathLibraryNumThreads(config);
EXPECT_EQ(num_thread, 10);
PD_ConfigSwitchIrDebug(config, TRUE);
PD_ConfigSetModelDir(config, model_dir.c_str());
PD_ConfigSetOptimCacheDir(config,
(FLAGS_infer_model + "/OptimCacheDir").c_str());
const char* model_dir_ = PD_ConfigGetModelDir(config);
LOG(INFO) << model_dir_;
PD_ConfigEnableUseGpu(config, 100, 0, 0);
bool use_gpu = PD_ConfigUseGpu(config);
EXPECT_TRUE(use_gpu);
int device_id = PD_ConfigGpuDeviceId(config);
EXPECT_EQ(device_id, 0);
int init_size = PD_ConfigMemoryPoolInitSizeMb(config);
EXPECT_EQ(init_size, 100);
float frac = PD_ConfigFractionOfGpuMemoryForPool(config);
LOG(INFO) << frac;
PD_ConfigEnableCudnn(config);
bool cudnn = PD_ConfigCudnnEnabled(config);
EXPECT_TRUE(cudnn);
PD_ConfigSwitchIrOptim(config, TRUE);
bool ir_optim = PD_ConfigIrOptim(config);
EXPECT_TRUE(ir_optim);
PD_ConfigEnableTensorRtEngine(
config, 1 << 20, 1, 3, PD_PRECISION_FLOAT32, FALSE, FALSE);
bool trt_enable = PD_ConfigTensorRtEngineEnabled(config);
EXPECT_TRUE(trt_enable);
PD_ConfigEnableMemoryOptim(config, true);
bool memory_optim_enable = PD_ConfigMemoryOptimEnabled(config);
EXPECT_TRUE(memory_optim_enable);
PD_ConfigEnableProfile(config);
bool profiler_enable = PD_ConfigProfileEnabled(config);
EXPECT_TRUE(profiler_enable);
PD_ConfigSetInvalid(config);
bool is_valid = PD_ConfigIsValid(config);
EXPECT_FALSE(is_valid);
PD_ConfigDestroy(config);
}
TEST(PD_Config, trt_int8) {
std::string model_dir = FLAGS_infer_model + "/mobilenet";
PD_Config* config = PD_ConfigCreate();
PD_ConfigEnableUseGpu(config, 100, 0, 0);
PD_ConfigEnableTensorRtEngine(
config, 1 << 20, 1, 3, PD_PRECISION_INT8, FALSE, TRUE);
bool trt_enable = PD_ConfigTensorRtEngineEnabled(config);
EXPECT_TRUE(trt_enable);
PD_ConfigDestroy(config);
}
TEST(PD_Config, trt_fp16) {
std::string model_dir = FLAGS_infer_model + "/mobilenet";
PD_Config* config = PD_ConfigCreate();
PD_ConfigEnableUseGpu(config, 100, 0, 0);
PD_ConfigEnableTensorRtEngine(
config, 1 << 20, 1, 3, PD_PRECISION_HALF, FALSE, FALSE);
bool trt_enable = PD_ConfigTensorRtEngineEnabled(config);
EXPECT_TRUE(trt_enable);
PD_Predictor* predictor = PD_PredictorCreate(config);
PD_PredictorDestroy(predictor);
}
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,95 @@
/* Copyright (c) 2021 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <string>
#include <vector>
#include "paddle/common/flags.h"
#include "paddle/fluid/inference/capi_exp/pd_inference_api.h"
PD_DEFINE_string(infer_model, "", "model path");
namespace paddle {
namespace inference {
namespace analysis {
void predictor_run() {
std::string model_dir = FLAGS_infer_model;
PD_Config* config = PD_ConfigCreate();
PD_ConfigDisableGpu(config);
PD_ConfigSetCpuMathLibraryNumThreads(config, 10);
PD_ConfigSwitchIrDebug(config, TRUE);
PD_ConfigSetModel(config,
(model_dir + "/inference.pdmodel").c_str(),
(model_dir + "/inference.pdiparams").c_str());
PD_Predictor* predictor = PD_PredictorCreate(config);
PD_OneDimArrayCstr* input_names = PD_PredictorGetInputNames(predictor);
LOG(INFO) << "The inputs' size is: " << input_names->size;
EXPECT_EQ(input_names->size, 1u);
PD_IOInfos* in_infos = PD_PredictorGetInputInfos(predictor);
EXPECT_EQ(in_infos->size, 1u);
PD_IOInfos* out_infos = PD_PredictorGetOutputInfos(predictor);
std::array<int32_t, 4> shape_0 = {1, 3, 224, 224};
std::array<float, 1 * 3 * 224 * 224> data_0 = {0};
PD_Tensor* input_0 = PD_PredictorGetInputHandle(predictor, "x");
PD_TensorReshape(input_0, 4, shape_0.data());
PD_TensorCopyFromCpuFloat(input_0, data_0.data());
LOG(INFO) << "Run Inference in CAPI encapsulation. ";
EXPECT_TRUE(PD_PredictorRun(predictor));
PD_OneDimArrayCstr* output_names = PD_PredictorGetOutputNames(predictor);
LOG(INFO) << "output size is: " << output_names->size;
for (size_t index = 0; index < output_names->size; ++index) {
LOG(INFO) << "output[" << index
<< "]'s name is: " << output_names->data[index];
PD_Tensor* output =
PD_PredictorGetOutputHandle(predictor, output_names->data[index]);
PD_OneDimArrayInt32* shape = PD_TensorGetShape(output);
LOG(INFO) << "output[" << index << "]'s shape_size is: " << shape->size;
int32_t out_size = 1;
for (size_t i = 0; i < shape->size; ++i) {
LOG(INFO) << "output[" << index << "]'s shape is: " << shape->data[i];
out_size = out_size * shape->data[i];
}
float* out_data = new float[out_size];
PD_TensorCopyToCpuFloat(output, out_data);
LOG(INFO) << "output[" << index << "]'s DATA is: " << out_data[0];
delete[] out_data;
PD_OneDimArrayInt32Destroy(shape);
PD_TensorDestroy(output);
}
PD_PredictorClearIntermediateTensor(predictor);
PD_PredictorTryShrinkMemory(predictor);
PD_OneDimArrayCstrDestroy(output_names);
PD_TensorDestroy(input_0);
PD_OneDimArrayCstrDestroy(input_names);
PD_IOInfosDestroy(in_infos);
PD_IOInfosDestroy(out_infos);
PD_PredictorDestroy(predictor);
}
#ifdef PADDLE_WITH_DNNL
TEST(PD_PredictorRun, predictor_run) { predictor_run(); }
#endif
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,113 @@
// Copyright (c) 2021 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <string>
#include <vector>
#include "paddle/common/flags.h"
#include "paddle/fluid/inference/capi_exp/pd_inference_api.h"
PD_DEFINE_string(infer_model, "", "model path");
namespace paddle {
namespace inference {
namespace analysis {
TEST(PD_PredictorRun, predictor_run) {
auto model_dir = FLAGS_infer_model;
PD_Config *config = PD_ConfigCreate();
PD_ConfigSetModel(config,
(model_dir + "/__model__").c_str(),
(model_dir + "/param").c_str());
PD_ConfigDisableGpu(config);
PD_Predictor *predictor = PD_PredictorCreate(config);
size_t input_num = PD_PredictorGetInputNum(predictor);
LOG(INFO) << "Input num: " << input_num;
size_t output_num = PD_PredictorGetOutputNum(predictor);
LOG(INFO) << "Output num: " << output_num;
PD_OneDimArrayCstr *input_names = PD_PredictorGetInputNames(predictor);
EXPECT_EQ(input_names->size, 2u);
LOG(INFO) << "Predictor start run!";
PD_Tensor *inputs[2]; // NOLINT
inputs[0] = PD_PredictorGetInputHandle(predictor, input_names->data[0]);
inputs[1] = PD_PredictorGetInputHandle(predictor, input_names->data[1]);
LOG(INFO) << "Predictor start run!";
// inputs[0]: word, use lod memory in stack
std::array<int32_t, 2> shape_0 = {11, 1};
std::array<int64_t, 11 * 1> data_0 = {
12673, 9763, 905, 284, 45, 7474, 20, 17, 1, 4, 9};
std::array<size_t, 2> lod_layer_0 = {0, 11};
PD_OneDimArraySize layer_0;
layer_0.size = 2;
layer_0.data = lod_layer_0.data();
PD_OneDimArraySize *layer_0_ptr = &layer_0;
PD_TwoDimArraySize lod_0;
lod_0.size = 1;
lod_0.data = &layer_0_ptr;
PD_TensorReshape(inputs[0], 2, shape_0.data());
PD_TensorCopyFromCpuInt64(inputs[0], data_0.data());
PD_TensorSetLod(inputs[0], &lod_0);
// inputs[1]: mention, use lod memory in heap
std::array<int32_t, 2> shape_1 = {11, 1};
std::array<int64_t, 11 * 1> data_1 = {27, 0, 0, 33, 34, 33, 0, 0, 0, 1, 2};
PD_TwoDimArraySize *lod_1_ptr = new PD_TwoDimArraySize();
lod_1_ptr->size = 1;
lod_1_ptr->data = new PD_OneDimArraySize *[1];
lod_1_ptr->data[0] = new PD_OneDimArraySize();
lod_1_ptr->data[0]->size = 2;
lod_1_ptr->data[0]->data = new size_t[2];
lod_1_ptr->data[0]->data[0] = 0;
lod_1_ptr->data[0]->data[1] = 11;
PD_TensorReshape(inputs[1], 2, shape_1.data());
PD_TensorCopyFromCpuInt64(inputs[1], data_1.data());
PD_TensorSetLod(inputs[1], lod_1_ptr);
// retrieve the lod memory
delete[] lod_1_ptr->data[0]->data;
delete lod_1_ptr->data[0];
delete[] lod_1_ptr->data;
delete lod_1_ptr;
lod_1_ptr = nullptr;
LOG(INFO) << "Predictor start run!";
bool success = PD_PredictorRun(predictor);
EXPECT_TRUE(success);
LOG(INFO) << "Predictor run success!";
PD_OneDimArrayCstr *output_names = PD_PredictorGetOutputNames(predictor);
PD_Tensor *output =
PD_PredictorGetOutputHandle(predictor, output_names->data[0]);
PD_TwoDimArraySize *output_lod = PD_TensorGetLod(output);
PD_TwoDimArraySizeDestroy(output_lod);
PD_TensorDestroy(output);
PD_OneDimArrayCstrDestroy(output_names);
PD_TensorDestroy(inputs[0]);
PD_TensorDestroy(inputs[1]);
PD_OneDimArrayCstrDestroy(input_names);
PD_PredictorDestroy(predictor);
}
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,116 @@
/* Copyright (c) 2021 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <string>
#include <vector>
#include "paddle/common/flags.h"
#include "paddle/fluid/inference/capi_exp/pd_inference_api.h"
PD_DEFINE_string(infer_model, "", "model path");
namespace paddle {
namespace inference {
namespace analysis {
TEST(PD_Config, interface) {
std::string model_dir = FLAGS_infer_model + "/mobilenet";
std::string prog_file = model_dir + "/__model__";
std::string param_file = model_dir + "/__params__";
std::string opt_cache_dir = FLAGS_infer_model + "/OptimCacheDir";
PD_Config* config = PD_ConfigCreate();
PD_ConfigSetModelDir(config, model_dir.c_str());
std::string model_dir_ = PD_ConfigGetModelDir(config);
EXPECT_EQ(model_dir, model_dir_);
PD_ConfigSetModel(config, prog_file.c_str(), param_file.c_str());
PD_ConfigSetProgFile(config, prog_file.c_str());
PD_ConfigSetParamsFile(config, param_file.c_str());
PD_ConfigSetOptimCacheDir(config, opt_cache_dir.c_str());
std::string prog_file_ = PD_ConfigGetProgFile(config);
std::string param_file_ = PD_ConfigGetParamsFile(config);
EXPECT_EQ(prog_file, prog_file_);
EXPECT_EQ(param_file, param_file_);
PD_ConfigDisableFCPadding(config);
bool fc_padding = PD_ConfigUseFcPadding(config);
EXPECT_FALSE(fc_padding);
PD_ConfigDisableGpu(config);
PD_ConfigSwitchIrOptim(config, TRUE);
bool ir_optim = PD_ConfigIrOptim(config);
EXPECT_TRUE(ir_optim);
PD_ConfigEnableMemoryOptim(config, true);
bool memory_enabled = PD_ConfigMemoryOptimEnabled(config);
EXPECT_TRUE(memory_enabled);
PD_ConfigSwitchIrDebug(config, TRUE);
#ifdef PADDLE_WITH_DNNL
const char* ops_name = "conv_2d";
PD_ConfigEnableONEDNN(config);
PD_ConfigSetOnednnOp(config, 1, &ops_name);
PD_ConfigSetOnednnCacheCapacity(config, 100);
bool onednn_enabled = PD_ConfigOnednnEnabled(config);
EXPECT_TRUE(onednn_enabled);
PD_ConfigSetCpuMathLibraryNumThreads(config, 10);
int32_t cpu_threads = PD_ConfigGetCpuMathLibraryNumThreads(config);
EXPECT_EQ(cpu_threads, 10);
PD_ConfigEnableOnednnBfloat16(config);
PD_ConfigSetBfloat16Op(config, 1, &ops_name);
PD_ConfigEnableOnednnInt8(config);
bool onednn_int8_enabled = PD_ConfigOnednnInt8Enabled(config);
EXPECT_TRUE(onednn_int8_enabled);
#endif
PD_ConfigEnableONNXRuntime(config);
bool onnxruntime_enabled = PD_ConfigONNXRuntimeEnabled(config);
#ifdef PADDLE_WITH_ONNXRUNTIME
EXPECT_TRUE(onnxruntime_enabled);
#else
EXPECT_FALSE(onnxruntime_enabled);
#endif
PD_ConfigDisableONNXRuntime(config);
bool onnxruntime_disabled = PD_ConfigONNXRuntimeEnabled(config);
EXPECT_FALSE(onnxruntime_disabled);
PD_ConfigEnableORTOptimization(config);
PD_ConfigEnableProfile(config);
bool profile_enabled = PD_ConfigProfileEnabled(config);
EXPECT_TRUE(profile_enabled);
PD_ConfigDisableGlogInfo(config);
bool glog_disabled = PD_ConfigGlogInfoDisabled(config);
EXPECT_TRUE(glog_disabled);
PD_ConfigSetInvalid(config);
bool is_valid = PD_ConfigIsValid(config);
EXPECT_FALSE(is_valid);
PD_ConfigDestroy(config);
}
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,211 @@
/* Copyright (c) 2021 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <numeric>
#include <sstream>
#include <string>
#include <vector>
#include "paddle/common/flags.h"
#include "paddle/fluid/inference/capi_exp/pd_inference_api.h"
PD_DEFINE_string(infer_model, "", "model path");
namespace paddle {
namespace inference {
namespace analysis {
void PD_run() {
auto model_dir = FLAGS_infer_model;
PD_Config* config = PD_ConfigCreate();
PD_ConfigSetModel(config,
(model_dir + "/__model__").c_str(),
(model_dir + "/__params__").c_str());
PD_Predictor* predictor = PD_PredictorCreate(config);
PD_OneDimArrayCstr* input_names = PD_PredictorGetInputNames(predictor);
PD_Tensor* tensor =
PD_PredictorGetInputHandle(predictor, input_names->data[0]);
std::array<int32_t, 4> shapes = {1, 3, 224, 224};
std::vector<float> input(1 * 3 * 224 * 224, 0);
int32_t size;
PD_PlaceType place;
PD_TensorReshape(tensor, 4, shapes.data());
PD_TensorCopyFromCpuFloat(tensor, input.data());
PD_TensorDataFloat(tensor, &place, &size);
PD_TensorMutableDataFloat(tensor, place);
PD_TwoDimArraySize lod;
lod.size = 0;
lod.data = nullptr;
PD_TensorSetLod(tensor, &lod);
PD_PredictorRun(predictor);
std::vector<float> out_data;
PD_OneDimArrayCstr* output_names = PD_PredictorGetOutputNames(predictor);
PD_Tensor* output_tensor =
PD_PredictorGetOutputHandle(predictor, output_names->data[0]);
PD_OneDimArrayInt32* output_shape = PD_TensorGetShape(output_tensor);
int32_t out_num = std::accumulate(output_shape->data,
output_shape->data + output_shape->size,
1,
std::multiplies<>());
out_data.resize(out_num);
PD_TensorCopyToCpuFloat(output_tensor, out_data.data());
LOG(INFO) << "Output tensor name is: " << PD_TensorGetName(output_tensor);
PD_DataType data_type = PD_TensorGetDataType(output_tensor);
EXPECT_EQ(data_type, PD_DATA_FLOAT32);
PD_TwoDimArraySize* out_lod = PD_TensorGetLod(output_tensor);
PD_TwoDimArraySizeDestroy(out_lod);
PD_OneDimArrayInt32Destroy(output_shape);
PD_TensorDestroy(output_tensor);
PD_OneDimArrayCstrDestroy(output_names);
PD_TensorDestroy(tensor);
PD_OneDimArrayCstrDestroy(input_names);
PD_PredictorDestroy(predictor);
}
TEST(PD_Tensor, PD_run) { PD_run(); }
TEST(PD_Tensor, int32) {
auto model_dir = FLAGS_infer_model;
PD_Config* config = PD_ConfigCreate();
PD_ConfigSetModel(config,
(model_dir + "/__model__").c_str(),
(model_dir + "/__params__").c_str());
PD_Predictor* predictor = PD_PredictorCreate(config);
PD_OneDimArrayCstr* input_names = PD_PredictorGetInputNames(predictor);
PD_Tensor* tensor =
PD_PredictorGetInputHandle(predictor, input_names->data[0]);
std::array<int32_t, 4> shapes = {1, 3, 224, 224};
std::vector<int32_t> input(1 * 3 * 224 * 224, 0);
int32_t size;
PD_PlaceType place;
PD_TensorReshape(tensor, 4, shapes.data());
PD_TensorCopyFromCpuInt32(tensor, input.data());
int32_t* data_ptr = PD_TensorDataInt32(tensor, &place, &size);
EXPECT_EQ(place, PD_PLACE_CPU);
EXPECT_EQ(size, 1 * 3 * 224 * 224);
int32_t* mutable_data_ptr = PD_TensorMutableDataInt32(tensor, place);
EXPECT_EQ(data_ptr, mutable_data_ptr);
PD_DataType data_type = PD_TensorGetDataType(tensor);
EXPECT_EQ(data_type, PD_DATA_INT32);
PD_TensorCopyToCpuInt32(tensor, input.data());
PD_TensorDestroy(tensor);
PD_OneDimArrayCstrDestroy(input_names);
PD_PredictorDestroy(predictor);
}
TEST(PD_Tensor, int64) {
auto model_dir = FLAGS_infer_model;
PD_Config* config = PD_ConfigCreate();
PD_ConfigSetModel(config,
(model_dir + "/__model__").c_str(),
(model_dir + "/__params__").c_str());
PD_Predictor* predictor = PD_PredictorCreate(config);
PD_OneDimArrayCstr* input_names = PD_PredictorGetInputNames(predictor);
PD_Tensor* tensor =
PD_PredictorGetInputHandle(predictor, input_names->data[0]);
std::array<int32_t, 4> shapes = {1, 3, 224, 224};
std::vector<int64_t> input(1 * 3 * 224 * 224, 0);
int32_t size;
PD_PlaceType place;
PD_TensorReshape(tensor, 4, shapes.data());
PD_TensorCopyFromCpuInt64(tensor, input.data());
int64_t* data_ptr = PD_TensorDataInt64(tensor, &place, &size);
EXPECT_EQ(place, PD_PLACE_CPU);
EXPECT_EQ(size, 1 * 3 * 224 * 224);
int64_t* mutable_data_ptr = PD_TensorMutableDataInt64(tensor, place);
EXPECT_EQ(data_ptr, mutable_data_ptr);
PD_DataType data_type = PD_TensorGetDataType(tensor);
EXPECT_EQ(data_type, PD_DATA_INT64);
PD_TensorCopyToCpuInt64(tensor, input.data());
PD_TensorDestroy(tensor);
PD_OneDimArrayCstrDestroy(input_names);
PD_PredictorDestroy(predictor);
}
TEST(PD_Tensor, uint8) {
auto model_dir = FLAGS_infer_model;
PD_Config* config = PD_ConfigCreate();
PD_ConfigSetModel(config,
(model_dir + "/__model__").c_str(),
(model_dir + "/__params__").c_str());
PD_Predictor* predictor = PD_PredictorCreate(config);
PD_OneDimArrayCstr* input_names = PD_PredictorGetInputNames(predictor);
PD_Tensor* tensor =
PD_PredictorGetInputHandle(predictor, input_names->data[0]);
std::array<int32_t, 4> shapes = {1, 3, 224, 224};
std::array<uint8_t, 1 * 3 * 224 * 224> input = {0};
int32_t size;
PD_PlaceType place;
PD_TensorReshape(tensor, 4, shapes.data());
PD_TensorCopyFromCpuUint8(tensor, input.data());
uint8_t* data_ptr = PD_TensorDataUint8(tensor, &place, &size);
EXPECT_EQ(place, PD_PLACE_CPU);
EXPECT_EQ(size, 1 * 3 * 224 * 224);
uint8_t* mutable_data_ptr = PD_TensorMutableDataUint8(tensor, place);
EXPECT_EQ(data_ptr, mutable_data_ptr);
PD_DataType data_type = PD_TensorGetDataType(tensor);
EXPECT_EQ(data_type, PD_DATA_UINT8);
PD_TensorCopyToCpuUint8(tensor, input.data());
PD_TensorDestroy(tensor);
PD_OneDimArrayCstrDestroy(input_names);
PD_PredictorDestroy(predictor);
}
std::string read_file(std::string filename) {
std::ifstream file(filename);
return std::string((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
}
TEST(PD_Tensor, from_buffer) {
PD_Config* config = PD_ConfigCreate();
std::string prog_file = FLAGS_infer_model + "/__model__";
std::string params_file = FLAGS_infer_model + "/__params__";
std::string prog_str = read_file(prog_file);
std::string params_str = read_file(params_file);
PD_ConfigSetModelBuffer(config,
prog_str.c_str(),
prog_str.size(),
params_str.c_str(),
params_str.size());
bool model_from_memory = PD_ConfigModelFromMemory(config);
EXPECT_TRUE(model_from_memory);
PD_ConfigDestroy(config);
}
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,117 @@
/* Copyright (c) 2021 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include "paddle/common/flags.h"
#include "paddle/fluid/inference/capi_exp/pd_inference_api.h"
PD_DEFINE_string(infer_model, "", "model path");
namespace paddle {
namespace inference {
namespace analysis {
typedef struct RunParameter {
PD_Predictor* predictor;
int32_t* shapes;
size_t shape_size;
float* input_data;
int32_t out_size;
std::vector<float> out_data;
int32_t thread_index;
} RunParameter;
void* run(void* thread_param) {
struct RunParameter* param = (struct RunParameter*)thread_param;
LOG(INFO) << "Thread " << param->thread_index << " start run!";
PD_OneDimArrayCstr* input_names = PD_PredictorGetInputNames(param->predictor);
PD_Tensor* tensor =
PD_PredictorGetInputHandle(param->predictor, input_names->data[0]);
PD_TensorReshape(tensor, param->shape_size, param->shapes);
PD_TensorCopyFromCpuFloat(tensor, param->input_data);
PD_PredictorRun(param->predictor);
PD_OneDimArrayCstr* output_names =
PD_PredictorGetOutputNames(param->predictor);
PD_Tensor* output_tensor =
PD_PredictorGetOutputHandle(param->predictor, output_names->data[0]);
PD_OneDimArrayInt32* output_shape = PD_TensorGetShape(output_tensor);
param->out_size = 1;
for (size_t index = 0; index < output_shape->size; ++index) {
param->out_size = param->out_size * output_shape->data[index];
}
PD_OneDimArrayInt32Destroy(output_shape);
param->out_data.resize(param->out_size);
PD_TensorCopyToCpuFloat(output_tensor, param->out_data.data());
PD_TensorDestroy(output_tensor);
PD_OneDimArrayCstrDestroy(output_names);
PD_TensorDestroy(tensor);
PD_OneDimArrayCstrDestroy(input_names);
LOG(INFO) << "Thread " << param->thread_index << " end run!";
return nullptr;
}
void threads_run(int thread_num) {
auto model_dir = FLAGS_infer_model;
PD_Config* config = PD_ConfigCreate();
PD_ConfigSetModel(config,
(model_dir + "/__model__").c_str(),
(model_dir + "/__params__").c_str());
PD_Predictor* predictor = PD_PredictorCreate(config);
std::vector<pthread_t> threads(thread_num);
std::vector<RunParameter> params(thread_num);
std::array<int32_t, 4> shapes = {1, 3, 224, 224};
std::vector<float> input(1 * 3 * 224 * 224, 0);
for (int i = 0; i < thread_num; ++i) {
params[i].predictor = PD_PredictorClone(predictor);
params[i].shapes = shapes.data();
params[i].shape_size = 4;
params[i].input_data = input.data();
params[i].out_size = 0;
params[i].thread_index = i;
pthread_create(&(threads[i]), nullptr, run, &(params[i]));
}
for (int i = 0; i < thread_num; ++i) {
pthread_join(threads[i], nullptr);
}
ASSERT_GT(params[0].out_size, 0);
for (int i = 1; i < thread_num; ++i) {
ASSERT_EQ(params[i].out_size, params[0].out_size);
for (int j = 0; j < params[i].out_size; ++j) {
ASSERT_EQ(params[i].out_data[j], params[0].out_data[j]);
}
}
for (int i = 0; i < thread_num; ++i) {
PD_PredictorDestroy(params[i].predictor);
}
PD_PredictorDestroy(predictor);
}
TEST(PD_Predictor, PD_multi_threads_run) { threads_run(10); }
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,90 @@
/* Copyright (c) 2021 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <string>
#include <vector>
#include "paddle/common/flags.h"
#include "paddle/fluid/inference/capi_exp/pd_config.h"
#include "paddle/fluid/inference/capi_exp/pd_inference_api.h"
#include "paddle/fluid/inference/capi_exp/pd_utils.h"
PD_DEFINE_string(infer_model, "", "model path");
namespace paddle {
namespace inference {
namespace analysis {
void predictor_run() {
std::string model_dir = FLAGS_infer_model;
std::string prog_file = model_dir + "/model";
std::string params_file = model_dir + "/params";
PD_Config *config = PD_ConfigCreate();
PD_ConfigDisableGpu(config);
PD_ConfigSetCpuMathLibraryNumThreads(config, 10);
PD_ConfigSwitchIrDebug(config, TRUE);
PD_ConfigSetModel(config, prog_file.c_str(), params_file.c_str());
PD_Cstr *config_summary = PD_ConfigSummary(config);
LOG(INFO) << config_summary->data;
PD_Predictor *predictor = PD_PredictorCreate(config);
PD_Tensor *tensor = PD_PredictorGetInputHandle(predictor, "data");
const int batch_size = 1;
const int channels = 3;
const int height = 318;
const int width = 318;
float *input = new float[batch_size * channels * height * width]();
std::array<int32_t, 4> shape = {batch_size, channels, height, width};
PD_TensorReshape(tensor, 4, shape.data());
PD_TensorCopyFromCpuFloat(tensor, input);
EXPECT_TRUE(PD_PredictorRun(predictor));
delete[] input;
PD_TensorDestroy(tensor);
PD_CstrDestroy(config_summary);
PD_PredictorDestroy(predictor);
}
TEST(PD_PredictorRun, predictor_run) { predictor_run(); }
#ifdef PADDLE_WITH_DNNL
TEST(PD_Config, profile_onednn) {
std::string model_dir = FLAGS_infer_model;
std::string prog_file = model_dir + "/model";
std::string params_file = model_dir + "/params";
PD_Config *config = PD_ConfigCreate();
PD_ConfigDisableGpu(config);
PD_ConfigSetCpuMathLibraryNumThreads(config, 10);
PD_ConfigSwitchIrDebug(config, TRUE);
PD_ConfigEnableONEDNN(config);
bool onednn_enable = PD_ConfigOnednnEnabled(config);
EXPECT_TRUE(onednn_enable);
PD_ConfigEnableOnednnBfloat16(config);
PD_ConfigSetOnednnCacheCapacity(config, 0);
PD_ConfigSetModel(config, prog_file.c_str(), params_file.c_str());
PD_ConfigDestroy(config);
}
#endif
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,66 @@
/* Copyright (c) 2021 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <string>
#include <vector>
#include "paddle/common/flags.h"
#include "paddle/fluid/inference/capi_exp/pd_inference_api.h"
PD_DEFINE_string(infer_model, "", "model path");
namespace paddle {
namespace inference {
namespace analysis {
#ifdef PADDLE_WITH_XPU
TEST(PD_Config, use_xpu) {
std::string model_dir = FLAGS_infer_model + "/mobilenet";
PD_Config *config = PD_Config();
PD_ConfigSwitchIrDebug(config, TRUE);
PD_ConfigSetModelDir(config, model_dir.c_str());
PD_ConfigSetOptimCacheDir(config,
(FLAGS_infer_model + "/OptimCacheDir").c_str());
const char *model_dir_ = PD_ConfigGetModelDir(config);
LOG(INFO) << model_dir_;
PD_ConfigEnableXpu(config, 0xfffc00);
bool use_xpu = PD_ConfigUseXpu(config);
EXPECT_TRUE(use_xpu);
int32_t device_id = PD_ConfigXpuDeviceId(config);
EXPECT_EQ(device_id, 0);
PD_ConfigSwitchIrOptim(config, TRUE);
bool ir_optim = PD_IrOptim(config);
EXPECT_TRUE(ir_optim);
PD_ConfigEnableMemoryOptim(config, true);
bool memory_optim_enable = PD_ConfigMemoryOptimEnabled(config);
EXPECT_TRUE(memory_optim_enable);
PD_ConfigEnableProfile(config);
bool profiler_enable = PD_ConfigProfileEnabled(config);
EXPECT_TRUE(profiler_enable);
PD_SetInValid(config);
bool is_valid = PD_ConfigIsValid(config);
EXPECT_FALSE(is_valid);
PD_ConfigDestroy(config);
}
#endif
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,181 @@
/* 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 <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string>
#include <vector>
#include "paddle/fluid/inference/capi/paddle_c_api.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
TEST(PD_AnalysisConfig, use_gpu) {
std::string model_dir = FLAGS_infer_model + "/mobilenet";
PD_AnalysisConfig *config = PD_NewAnalysisConfig();
PD_DisableGpu(config);
PD_SetCpuMathLibraryNumThreads(config, 10);
int num_thread = PD_CpuMathLibraryNumThreads(config);
PADDLE_ENFORCE_EQ(
10,
num_thread,
common::errors::InvalidArgument("The num of thread should be "
"equal to 10, but got %d.",
num_thread));
PD_SwitchSpecifyInputNames(config, true);
PD_SwitchIrDebug(config, true);
PD_SetModel(config, model_dir.c_str(), nullptr);
PD_SetOptimCacheDir(config, (FLAGS_infer_model + "/OptimCacheDir").c_str());
const char *model_dir_ = PD_ModelDir(config);
LOG(INFO) << model_dir_;
PD_EnableUseGpu(config, 100, 0);
bool use_gpu = PD_UseGpu(config);
PADDLE_ENFORCE_EQ(use_gpu,
true,
common::errors::InvalidArgument(
"GPU is not enabled. "
"The configuration indicates that GPU should be used, "
"but it is currently disabled. "
"Please check your configuration settings and ensure "
"that GPU is properly enabled."));
int device = PD_GpuDeviceId(config);
PADDLE_ENFORCE_EQ(device,
0,
common::errors::InvalidArgument(
"The device ID is incorrect. "
"Expected device ID is 0, but received %d. "
"Please check your device configuration and "
"ensure the correct device ID is used.",
device));
int init_size = PD_MemoryPoolInitSizeMb(config);
PADDLE_ENFORCE_EQ(init_size,
100,
common::errors::InvalidArgument(
"The initial size of the memory pool is incorrect. "
"Expected size is 100 MB, but received %d MB. "
"Please check your configuration settings and ensure "
"the correct memory pool size is set.",
init_size));
float frac = PD_FractionOfGpuMemoryForPool(config);
LOG(INFO) << frac;
PD_EnableCUDNN(config);
bool cudnn = PD_CudnnEnabled(config);
PADDLE_ENFORCE_EQ(cudnn,
true,
common::errors::InvalidArgument(
"cuDNN is not enabled. "
"The configuration indicates that cuDNN should be "
"enabled, but it is currently disabled. "
"Please check your configuration settings and ensure "
"that cuDNN is properly enabled."));
PD_SwitchIrOptim(config, true);
bool ir_optim = PD_IrOptim(config);
PADDLE_ENFORCE_EQ(ir_optim,
true,
common::errors::InvalidArgument(
"IR optimization is not enabled. "
"The configuration indicates that IR optimization "
"should be enabled, but it is currently disabled. "
"Please check your configuration settings and ensure "
"that IR optimization is properly enabled."));
PD_EnableTensorRtEngine(
config, 1 << 20, 1, 3, Precision::kFloat32, false, false);
bool trt_enable = PD_TensorrtEngineEnabled(config);
PADDLE_ENFORCE_EQ(trt_enable,
true,
common::errors::InvalidArgument(
"TensorRT engine is not enabled. "
"The configuration indicates that TensorRT engine "
"should be enabled, but it is currently disabled. "
"Please check your configuration settings and ensure "
"that TensorRT engine is properly enabled."));
PD_EnableMemoryOptim(config);
bool memory_optim_enable = PD_MemoryOptimEnabled(config);
PADDLE_ENFORCE_EQ(memory_optim_enable,
true,
common::errors::InvalidArgument(
"Memory optimization is not enabled. "
"The configuration indicates that memory optimization "
"should be enabled, but it is currently disabled. "
"Please check your configuration settings and ensure "
"that memory optimization is properly enabled."));
PD_EnableProfile(config);
bool profiler_enable = PD_ProfileEnabled(config);
PADDLE_ENFORCE_EQ(profiler_enable,
true,
common::errors::InvalidArgument(
"Profiler is not enabled. "
"The configuration indicates that the profiler should "
"be enabled, but it is currently disabled. "
"Please check your configuration settings and ensure "
"that the profiler is properly enabled."));
PD_SetInValid(config);
bool is_valid = PD_IsValid(config);
PADDLE_ENFORCE_EQ(
is_valid,
true,
common::errors::InvalidArgument(
"Configuration is not valid. "
"The configuration should be valid, but it is currently invalid. "
"Please check your configuration settings and ensure they are "
"correct."));
PD_DeleteAnalysisConfig(config);
}
TEST(PD_AnalysisConfig, trt_int8) {
std::string model_dir = FLAGS_infer_model + "/mobilenet";
PD_AnalysisConfig *config = PD_NewAnalysisConfig();
PD_EnableUseGpu(config, 100, 0);
PD_EnableTensorRtEngine(config, 1 << 20, 1, 3, Precision::kInt8, false, true);
bool trt_enable = PD_TensorrtEngineEnabled(config);
PADDLE_ENFORCE_EQ(trt_enable,
true,
common::errors::InvalidArgument(
"TensorRT engine is not enabled. "
"The configuration indicates that TensorRT engine "
"should be enabled, but it is currently disabled. "
"Please check your configuration settings and ensure "
"that TensorRT engine is properly enabled."));
PD_DeleteAnalysisConfig(config);
}
TEST(PD_AnalysisConfig, trt_fp16) {
std::string model_dir = FLAGS_infer_model + "/mobilenet";
PD_AnalysisConfig *config = PD_NewAnalysisConfig();
PD_EnableUseGpu(config, 100, 0);
PD_EnableTensorRtEngine(
config, 1 << 20, 1, 3, Precision::kHalf, false, false);
bool trt_enable = PD_TensorrtEngineEnabled(config);
PADDLE_ENFORCE_EQ(trt_enable,
true,
common::errors::InvalidArgument(
"TensorRT engine is not enabled. "
"The configuration indicates that TensorRT engine "
"should be enabled, but it is currently disabled. "
"Please check your configuration settings and ensure "
"that TensorRT engine is properly enabled."));
PD_Predictor *predictor = PD_NewPredictor(config);
PD_DeletePredictor(predictor);
PD_DeleteAnalysisConfig(config);
}
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,105 @@
/* 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 <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string>
#include <vector>
#include "paddle/fluid/inference/capi/paddle_c_api.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
void zero_copy_run() {
std::string model_dir = FLAGS_infer_model;
PD_AnalysisConfig *config = PD_NewAnalysisConfig();
PD_DisableGpu(config);
PD_SetCpuMathLibraryNumThreads(config, 10);
PD_SwitchSpecifyInputNames(config, true);
PD_SwitchIrDebug(config, true);
PD_SetModel(config, model_dir.c_str(), nullptr);
bool use_feed_fetch = PD_UseFeedFetchOpsEnabled(config);
PADDLE_ENFORCE_EQ(
use_feed_fetch, false, common::errors::PreconditionNotMet("NO"));
bool specify_input_names = PD_SpecifyInputName(config);
PADDLE_ENFORCE_EQ(
specify_input_names, true, common::errors::PreconditionNotMet("NO"));
const int batch_size = 1;
const int channels = 3;
const int height = 224;
const int width = 224;
float input[batch_size * channels * height * width] = {0};
int shape[4] = {batch_size, channels, height, width};
int shape_size = 4;
int in_size = 2;
int out_size;
PD_ZeroCopyData *inputs = new PD_ZeroCopyData[2];
PD_ZeroCopyData *outputs = nullptr;
inputs[0].data = static_cast<void *>(input);
inputs[0].dtype = PD_FLOAT32;
inputs[0].name = new char[6];
inputs[0].name[0] = 'i';
inputs[0].name[1] = 'm';
inputs[0].name[2] = 'a';
inputs[0].name[3] = 'g';
inputs[0].name[4] = 'e';
inputs[0].name[5] = '\0';
inputs[0].shape = shape;
inputs[0].shape_size = shape_size;
int *label = new int[1];
label[0] = 0;
inputs[1].data = static_cast<void *>(label);
inputs[1].dtype = PD_INT64;
inputs[1].name = new char[6];
inputs[1].name[0] = 'l';
inputs[1].name[1] = 'a';
inputs[1].name[2] = 'b';
inputs[1].name[3] = 'e';
inputs[1].name[4] = 'l';
inputs[1].name[5] = '\0';
int label_shape[2] = {1, 1};
int label_shape_size = 2;
inputs[1].shape = label_shape;
inputs[1].shape_size = label_shape_size;
PD_PredictorZeroCopyRun(config, inputs, in_size, &outputs, &out_size);
LOG(INFO) << "output size is: " << out_size;
LOG(INFO) << outputs[0].name;
for (int j = 0; j < out_size; ++j) {
LOG(INFO) << "output[" << j
<< "]'s shape_size is: " << outputs[j].shape_size;
for (int i = 0; i < outputs[0].shape_size; ++i) {
LOG(INFO) << "output[" << j << "]'s shape is: " << outputs[j].shape[i];
}
LOG(INFO) << "output[" << j
<< "]'s DATA is: " << *(static_cast<float *>(outputs[j].data));
}
delete[] outputs;
delete[] inputs;
}
#ifdef PADDLE_WITH_DNNL
TEST(PD_ZeroCopyRun, zero_copy_run) { zero_copy_run(); }
#endif
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,125 @@
// Copyright (c) 2020 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 <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string>
#include <vector>
#include "paddle/fluid/inference/capi/paddle_c_api.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
void SetConfig(PD_AnalysisConfig *config) {
auto model_dir = FLAGS_infer_model;
PD_SetModel(config,
(model_dir + "/__model__").c_str(),
(model_dir + "/param").c_str());
PD_SwitchSpecifyInputNames(config, true);
PD_DisableGpu(config);
}
TEST(PD_ZeroCopyRun, zero_copy_run) {
PD_AnalysisConfig *config = PD_NewAnalysisConfig();
SetConfig(config);
PD_Predictor *predictor = PD_NewPredictor(config);
int input_num = PD_GetInputNum(predictor);
printf("Input num: %d\n", input_num);
int output_num = PD_GetOutputNum(predictor);
printf("Output num: %d\n", output_num);
PD_ZeroCopyTensor inputs[2];
// inputs[0]: word
PD_InitZeroCopyTensor(&inputs[0]);
inputs[0].name = new char[5];
snprintf(inputs[0].name,
strlen(PD_GetInputName(predictor, 0)) + 1,
"%s",
PD_GetInputName(predictor, 0));
inputs[0].data.capacity = sizeof(int64_t) * 11 * 1;
inputs[0].data.length = inputs[0].data.capacity;
inputs[0].data.data = malloc(inputs[0].data.capacity);
std::vector<int64_t> ref_word(
{12673, 9763, 905, 284, 45, 7474, 20, 17, 1, 4, 9});
inputs[0].data.data = reinterpret_cast<void *>(ref_word.data());
int shape0[] = {11, 1};
inputs[0].shape.data = reinterpret_cast<void *>(shape0);
inputs[0].shape.capacity = sizeof(shape0);
inputs[0].shape.length = sizeof(shape0);
inputs[0].dtype = PD_INT64;
size_t lod0[] = {0, 11};
inputs[0].lod.data = reinterpret_cast<void *>(lod0);
inputs[0].lod.capacity = sizeof(size_t) * 2;
inputs[0].lod.length = sizeof(size_t) * 2;
PD_SetZeroCopyInput(predictor, &inputs[0]);
// inputs[1]: mention
PD_InitZeroCopyTensor(&inputs[1]);
inputs[1].name = new char[8];
snprintf(inputs[1].name,
strlen(PD_GetInputName(predictor, 1)) + 1,
"%s",
PD_GetInputName(predictor, 1));
inputs[1].data.capacity = sizeof(int64_t) * 11 * 1;
inputs[1].data.length = inputs[1].data.capacity;
inputs[1].data.data = malloc(inputs[1].data.capacity);
std::vector<int64_t> ref_mention({27, 0, 0, 33, 34, 33, 0, 0, 0, 1, 2});
inputs[1].data.data = reinterpret_cast<void *>(ref_mention.data());
int shape1[] = {11, 1};
inputs[1].shape.data = reinterpret_cast<void *>(shape1);
inputs[1].shape.capacity = sizeof(shape1);
inputs[1].shape.length = sizeof(shape1);
inputs[1].dtype = PD_INT64;
size_t lod1[] = {0, 11};
inputs[1].lod.data = reinterpret_cast<void *>(lod1);
inputs[1].lod.capacity = sizeof(size_t) * 2;
inputs[1].lod.length = sizeof(size_t) * 2;
PD_SetZeroCopyInput(predictor, &inputs[1]);
PD_ZeroCopyRun(predictor);
PD_ZeroCopyTensor output;
PD_InitZeroCopyTensor(&output);
output.name = new char[21];
snprintf(output.name,
strlen(PD_GetOutputName(predictor, 0)) + 1,
"%s",
PD_GetOutputName(predictor, 0));
// not necessary, just for coverage tests
output.lod.data = std::malloc(sizeof(size_t));
PD_GetZeroCopyOutput(predictor, &output);
PD_DestroyZeroCopyTensor(&output);
PD_DeleteAnalysisConfig(config);
PD_DeletePredictor(predictor);
}
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,173 @@
/* 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 <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include "paddle/common/enforce.h"
#include "paddle/fluid/inference/capi/c_api_internal.h"
#include "paddle/fluid/inference/capi/paddle_c_api.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
void PD_run() {
PD_AnalysisConfig* config = PD_NewAnalysisConfig();
std::string prog_file = FLAGS_infer_model + "/__model__";
std::string params_file = FLAGS_infer_model + "/__params__";
PD_SetModel(config, prog_file.c_str(), params_file.c_str());
PD_SetProgFile(config, prog_file.c_str());
PD_SetParamsFile(config, params_file.c_str());
LOG(INFO) << PD_ProgFile(config);
LOG(INFO) << PD_ParamsFile(config);
PD_Tensor* input = PD_NewPaddleTensor();
PD_PaddleBuf* buf = PD_NewPaddleBuf();
LOG(INFO) << "PaddleBuf empty: " << PD_PaddleBufEmpty(buf);
int batch = 1;
int channel = 3;
int height = 300;
int width = 300;
int shape[4] = {batch, channel, height, width};
int shape_size = 4;
float* data = new float[batch * channel * height * width];
PD_PaddleBufReset(buf,
static_cast<void*>(data),
sizeof(float) * (batch * channel * height * width));
char name[6] = {'i', 'm', 'a', 'g', 'e', '\0'};
PD_SetPaddleTensorName(input, name);
PD_SetPaddleTensorDType(input, PD_FLOAT32);
PD_SetPaddleTensorShape(input, shape, shape_size);
PD_SetPaddleTensorData(input, buf);
PD_Tensor* out_data = PD_NewPaddleTensor();
int out_size;
PD_PredictorRun(config, input, 1, &out_data, &out_size, 1);
LOG(INFO) << out_size;
LOG(INFO) << PD_GetPaddleTensorName(out_data);
LOG(INFO) << PD_GetPaddleTensorDType(out_data);
PD_PaddleBuf* b = PD_GetPaddleTensorData(out_data);
LOG(INFO) << PD_PaddleBufLength(b) / sizeof(float);
float* result = static_cast<float*>(PD_PaddleBufData(b));
LOG(INFO) << *result;
PD_DeletePaddleTensor(input);
int size;
const int* out_shape = PD_GetPaddleTensorShape(out_data, &size);
PADDLE_ENFORCE_EQ(
size,
2,
common::errors::InvalidArgument("The Output shape's size is NOT match."));
std::vector<int> ref_outshape_size({9, 6});
for (int i = 0; i < 2; ++i) {
PADDLE_ENFORCE_EQ(out_shape[i],
ref_outshape_size[i],
common::errors::InvalidArgument(
"The Output shape's size is NOT match."));
}
PD_DeletePaddleBuf(buf);
}
TEST(PD_Tensor, PD_run) { PD_run(); }
TEST(PD_Tensor, int32) {
PD_Tensor* input = PD_NewPaddleTensor();
PD_SetPaddleTensorDType(input, PD_INT32);
LOG(INFO) << PD_GetPaddleTensorDType(input);
}
TEST(PD_Tensor, int64) {
PD_Tensor* input = PD_NewPaddleTensor();
PD_SetPaddleTensorDType(input, PD_INT64);
LOG(INFO) << PD_GetPaddleTensorDType(input);
}
TEST(PD_Tensor, int8) {
PD_Tensor* input = PD_NewPaddleTensor();
PD_SetPaddleTensorDType(input, PD_UINT8);
LOG(INFO) << PD_GetPaddleTensorDType(input);
}
std::string read_file(std::string filename) {
std::ifstream file(filename);
return std::string((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
}
void buffer_run() {
PD_AnalysisConfig* config = PD_NewAnalysisConfig();
std::string prog_file = FLAGS_infer_model + "/__model__";
std::string params_file = FLAGS_infer_model + "/__params__";
std::string prog_str = read_file(prog_file);
std::string params_str = read_file(params_file);
PD_SetModelBuffer(config,
prog_str.c_str(),
prog_str.size(),
params_str.c_str(),
params_str.size());
LOG(INFO) << PD_ProgFile(config);
LOG(INFO) << PD_ParamsFile(config);
PADDLE_ENFORCE(PD_ModelFromMemory(config),
common::errors::PreconditionNotMet(
"PD_ModelFromMemory(config) is failed"));
PD_Tensor* input = PD_NewPaddleTensor();
PD_PaddleBuf* buf = PD_NewPaddleBuf();
LOG(INFO) << "PaddleBuf empty: " << PD_PaddleBufEmpty(buf);
int batch = 1;
int channel = 3;
int height = 300;
int width = 300;
int shape[4] = {batch, channel, height, width};
int shape_size = 4;
float* data = new float[batch * channel * height * width];
PD_PaddleBufReset(buf,
static_cast<void*>(data),
sizeof(float) * (batch * channel * height * width));
char name[6] = {'i', 'm', 'a', 'g', 'e', '\0'};
PD_SetPaddleTensorName(input, name);
PD_SetPaddleTensorDType(input, PD_FLOAT32);
PD_SetPaddleTensorShape(input, shape, shape_size);
PD_SetPaddleTensorData(input, buf);
PD_Tensor* out_data = PD_NewPaddleTensor();
int out_size;
PD_PredictorRun(config, input, 1, &out_data, &out_size, 1);
LOG(INFO) << out_size;
LOG(INFO) << PD_GetPaddleTensorName(out_data);
LOG(INFO) << PD_GetPaddleTensorDType(out_data);
PD_PaddleBuf* b = PD_GetPaddleTensorData(out_data);
LOG(INFO) << PD_PaddleBufLength(b) / sizeof(float);
float* result = static_cast<float*>(PD_PaddleBufData(b));
LOG(INFO) << *result;
PD_DeletePaddleTensor(input);
PD_DeletePaddleBuf(buf);
}
TEST(SetModelBuffer, read) { buffer_run(); }
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,98 @@
/* 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 <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string>
#include <vector>
#include "paddle/fluid/inference/capi/paddle_c_api.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
void zero_copy_run() {
std::string model_dir = FLAGS_infer_model;
std::string prog_file = model_dir + "/model";
std::string params_file = model_dir + "/params";
PD_AnalysisConfig *config = PD_NewAnalysisConfig();
PD_DisableGpu(config);
PD_SetCpuMathLibraryNumThreads(config, 10);
PD_SwitchSpecifyInputNames(config, true);
PD_SwitchIrDebug(config, true);
PD_SetModel(config, prog_file.c_str(), params_file.c_str());
bool use_feed_fetch = PD_UseFeedFetchOpsEnabled(config);
EXPECT_FALSE(use_feed_fetch);
bool specify_input_names = PD_SpecifyInputName(config);
EXPECT_TRUE(specify_input_names);
const int batch_size = 1;
const int channels = 3;
const int height = 318;
const int width = 318;
float *input = new float[batch_size * channels * height * width]();
int shape[4] = {batch_size, channels, height, width};
int shape_size = 4;
int in_size = 1;
int out_size;
PD_ZeroCopyData *inputs = new PD_ZeroCopyData;
PD_ZeroCopyData *outputs = new PD_ZeroCopyData;
inputs->data = static_cast<void *>(input);
inputs->dtype = PD_FLOAT32;
inputs->name = new char[5];
inputs->name[0] = 'd';
inputs->name[1] = 'a';
inputs->name[2] = 't';
inputs->name[3] = 'a';
inputs->name[4] = '\0';
inputs->shape = shape;
inputs->shape_size = shape_size;
PD_PredictorZeroCopyRun(config, inputs, in_size, &outputs, &out_size);
delete[] input;
delete[] inputs;
delete[] outputs;
}
TEST(PD_PredictorZeroCopyRun, zero_copy_run) { zero_copy_run(); }
#ifdef PADDLE_WITH_DNNL
TEST(PD_AnalysisConfig, profile_onednn) {
std::string model_dir = FLAGS_infer_model;
std::string prog_file = model_dir + "/model";
std::string params_file = model_dir + "/params";
PD_AnalysisConfig *config = PD_NewAnalysisConfig();
PD_DisableGpu(config);
PD_SetCpuMathLibraryNumThreads(config, 10);
PD_SwitchSpecifyInputNames(config, true);
PD_SwitchIrDebug(config, true);
PD_EnableONEDNN(config);
bool onednn_enable = PD_OnednnEnabled(config);
EXPECT_TRUE(onednn_enable);
PD_EnableOnednnBfloat16(config);
PD_SetOnednnCacheCapacity(config, 0);
PD_SetModel(config, prog_file.c_str(), params_file.c_str());
PD_DeleteAnalysisConfig(config);
}
#endif
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,65 @@
/* 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 <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string>
#include <vector>
#include "paddle/common/enforce.h"
#include "paddle/fluid/inference/capi/paddle_c_api.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
#ifdef PADDLE_WITH_XPU
TEST(PD_AnalysisConfig, use_xpu) {
std::string model_dir = FLAGS_infer_model + "/mobilenet";
PD_AnalysisConfig *config = PD_NewAnalysisConfig();
PD_SwitchSpecifyInputNames(config, true);
PD_SwitchIrDebug(config, true);
PD_SetModel(config, model_dir.c_str(), nullptr);
PD_SetOptimCacheDir(config, (FLAGS_infer_model + "/OptimCacheDir").c_str());
const char *model_dir_ = PD_ModelDir(config);
LOG(INFO) << model_dir_;
PD_EnableXpu(config, 0xfffc00);
bool use_xpu = PD_UseXpu(config);
PADDLE_ENFORCE_EQ(use_xpu, true, common::errors::PreconditionNotMet("NO"));
int device = PD_XpuDeviceId(config);
PADDLE_ENFORCE_EQ(device, 0, common::errors::PreconditionNotMet("NO"));
PD_SwitchIrOptim(config, true);
bool ir_optim = PD_IrOptim(config);
PADDLE_ENFORCE_EQ(ir_optim, true, common::errors::PreconditionNotMet("NO"));
PD_EnableMemoryOptim(config);
bool memory_optim_enable = PD_MemoryOptimEnabled(config);
PADDLE_ENFORCE_EQ(
memory_optim_enable, true, common::errors::PreconditionNotMet("NO"));
PD_EnableProfile(config);
bool profiler_enable = PD_ProfileEnabled(config);
PADDLE_ENFORCE_EQ(
profiler_enable, true, common::errors::PreconditionNotMet("NO"));
PD_SetInValid(config);
bool is_valid = PD_IsValid(config);
PADDLE_ENFORCE_EQ(is_valid, false, common::errors::PreconditionNotMet("NO"));
PD_DeleteAnalysisConfig(config);
}
#endif
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,332 @@
// 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 <vector>
#include "paddle/fluid/inference/analysis/helper.h"
#include "test/cpp/inference/api/tester_helper.h"
const int FLAGS_max_turn_num = 1;
namespace paddle {
namespace inference {
constexpr int32_t kMaxTurnLen = 50;
static std::vector<float> result_data;
struct DataRecord {
std::vector<std::vector<int64_t>> *turns;
std::vector<std::vector<float>> *turns_mask;
std::vector<std::vector<int64_t>> response; // response data : 1
std::vector<std::vector<float>> response_mask; // response mask data : 1
size_t batch_iter{0};
size_t batch_size{1};
size_t num_samples; // total number of samples
DataRecord() { // NOLINT
turns = new std::vector<std::vector<
int64_t>>[FLAGS_max_turn_num]; // turns data : FLAGS_max_turn_num
turns_mask = new std::vector<std::vector<
float>>[FLAGS_max_turn_num]; // turns mask data : FLAGS_max_turn_num
}
explicit DataRecord(const std::string &path, int batch_size = 1)
: DataRecord() {
this->batch_size = batch_size;
Load(path);
}
~DataRecord() { // NOLINT
delete[] turns;
delete[] turns_mask;
}
DataRecord NextBatch() {
DataRecord data;
size_t batch_end = batch_iter + batch_size;
// NOTE skip the final batch, if no enough data is provided.
if (batch_end <= response.size()) {
for (int i = 0; i < FLAGS_max_turn_num; ++i) {
data.turns[i].assign(turns[i].begin() + batch_iter,
turns[i].begin() + batch_end);
}
for (int i = 0; i < FLAGS_max_turn_num; ++i) {
data.turns_mask[i].assign(turns_mask[i].begin() + batch_iter,
turns_mask[i].begin() + batch_end);
}
data.response.assign(response.begin() + batch_iter,
response.begin() + batch_end);
data.response_mask.assign(response_mask.begin() + batch_iter,
response_mask.begin() + batch_end);
PADDLE_ENFORCE_EQ(!data.response.empty(),
true,
common::errors::Fatal(
"Variable `data` response is empty, please check"));
PADDLE_ENFORCE_EQ(
!data.response_mask.empty(),
true,
common::errors::Fatal(
"Variable `data` response mask is empty, please check"));
PADDLE_ENFORCE_EQ(data.response.size(),
data.response_mask.size(),
common::errors::InvalidArgument(
"Required data.response.size() should be equal to "
"data.response_mask.size() . "));
}
batch_iter += batch_size;
return data;
}
void Load(const std::string &path) {
std::ifstream file(path);
std::string line;
size_t num_lines = 0;
result_data.clear();
while (std::getline(file, line)) {
num_lines++;
std::vector<std::string> data;
split(line, ',', &data);
PADDLE_ENFORCE_EQ(data.size(),
(size_t)(2 * FLAGS_max_turn_num + 3),
common::errors::InvalidArgument(
"Required data.size() should be equal to "
"(size_t)(2 * FLAGS_max_turn_num + 3) . "));
// load turn data
std::vector<int64_t> turns_tmp[FLAGS_max_turn_num];
for (int i = 0; i < FLAGS_max_turn_num; ++i) {
split_to_int64(data[i], ' ', &turns_tmp[i]);
turns[i].push_back(std::move(turns_tmp[i]));
}
// load turn_mask data
std::vector<float> turns_mask_tmp[FLAGS_max_turn_num];
for (int i = 0; i < FLAGS_max_turn_num; ++i) {
split_to_float(data[FLAGS_max_turn_num + i], ' ', &turns_mask_tmp[i]);
turns_mask[i].push_back(std::move(turns_mask_tmp[i]));
}
// load response data
std::vector<int64_t> response_tmp;
split_to_int64(data[2 * FLAGS_max_turn_num], ' ', &response_tmp);
response.push_back(std::move(response_tmp));
// load response_mask data
std::vector<float> response_mask_tmp;
split_to_float(data[2 * FLAGS_max_turn_num + 1], ' ', &response_mask_tmp);
response_mask.push_back(std::move(response_mask_tmp));
// load result data
float result_tmp;
result_tmp = std::stof(data[2 * FLAGS_max_turn_num + 2]);
result_data.push_back(result_tmp);
}
num_samples = num_lines;
}
};
void PrepareInputs(std::vector<PaddleTensor> *input_slots,
DataRecord *data,
int batch_size) {
PaddleTensor turns_tensor[FLAGS_max_turn_num]; // NOLINT
PaddleTensor turns_mask_tensor[FLAGS_max_turn_num]; // NOLINT
PaddleTensor response_tensor;
PaddleTensor response_mask_tensor;
std::string turn_pre = "turn_";
std::string turn_mask_pre = "turn_mask_";
auto one_batch = data->NextBatch();
PADDLE_ENFORCE(
!one_batch.response.empty(),
::common::errors::Fatal("The response of one batch is empty."));
int size = one_batch.response[0].size();
PADDLE_ENFORCE_EQ(size,
kMaxTurnLen,
common::errors::InvalidArgument(
"Required size should be equal to kMaxTurnLen . "));
// turn tensor assignment
for (int i = 0; i < FLAGS_max_turn_num; ++i) {
turns_tensor[i].name = turn_pre + std::to_string(i);
turns_tensor[i].shape.assign({batch_size, size, 1});
turns_tensor[i].dtype = PaddleDType::INT64;
TensorAssignData<int64_t>(&turns_tensor[i], one_batch.turns[i]);
}
// turn mask tensor assignment
for (int i = 0; i < FLAGS_max_turn_num; ++i) {
turns_mask_tensor[i].name = turn_mask_pre + std::to_string(i);
turns_mask_tensor[i].shape.assign({batch_size, size, 1});
turns_mask_tensor[i].dtype = PaddleDType::FLOAT32;
TensorAssignData<float>(&turns_mask_tensor[i], one_batch.turns_mask[i]);
}
// response tensor assignment
response_tensor.name = "response";
response_tensor.shape.assign({batch_size, size, 1});
response_tensor.dtype = PaddleDType::INT64;
TensorAssignData<int64_t>(&response_tensor, one_batch.response);
// response mask tensor assignment
response_mask_tensor.name = "response_mask";
response_mask_tensor.shape.assign({batch_size, size, 1});
response_mask_tensor.dtype = PaddleDType::FLOAT32;
TensorAssignData<float>(&response_mask_tensor, one_batch.response_mask);
// Set inputs.
for (auto &item : turns_tensor) {
input_slots->push_back(std::move(item));
}
for (auto &item : turns_mask_tensor) {
input_slots->push_back(std::move(item));
}
input_slots->push_back(std::move(response_tensor));
input_slots->push_back(std::move(response_mask_tensor));
}
/*
* this model is unreasonable, it set a output tensor persistable, so
* ridiculous! so I disable constant_folding_pass
*/
void SetConfig(AnalysisConfig *cfg) {
cfg->SetModel(FLAGS_infer_model + "/__model__", FLAGS_infer_model + "/param");
cfg->SwitchSpecifyInputNames();
cfg->DeletePass("constant_folding_pass");
cfg->SwitchIrOptim(true);
}
void SetOptimConfig(AnalysisConfig *cfg) {
std::string optimModelPath = FLAGS_infer_model + "/saved_optim_model";
cfg->SetModel(optimModelPath + "/model", optimModelPath + "/params");
cfg->SwitchIrOptim(true);
cfg->SwitchSpecifyInputNames();
}
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
DataRecord data(FLAGS_infer_data, FLAGS_batch_size);
std::vector<PaddleTensor> input_slots;
int test_batch_num =
FLAGS_test_all_data ? data.num_samples / FLAGS_batch_size : 1; // NOLINT
LOG(INFO) << "The number of samples to be test: "
<< test_batch_num * FLAGS_batch_size;
for (int bid = 0; bid < test_batch_num; ++bid) {
input_slots.clear();
PrepareInputs(&input_slots, &data, FLAGS_batch_size);
(*inputs).emplace_back(input_slots);
}
}
// Easy for profiling independently.
void profile(bool use_onednn = false) {
AnalysisConfig cfg;
SetConfig(&cfg);
if (use_onednn) {
cfg.EnableONEDNN();
// Enable all the onednn supported ops except conv3d in dam
std::unordered_set<std::string> op_list = {
"softmax", "elementwise_add", "relu", "fc"};
cfg.SetONEDNNOp(op_list);
} else {
cfg.DisableONEDNN();
}
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all,
&outputs,
FLAGS_num_threads);
if (FLAGS_num_threads == 1 && !FLAGS_test_all_data) {
PADDLE_ENFORCE_GT(outputs.size(),
0,
::common::errors::Fatal(
"The size of outputs should be greater than 0."));
auto output = outputs.back();
PADDLE_ENFORCE_GT(output.size(),
0,
::common::errors::Fatal(
"The size of output should be greater than 0."));
size_t size = GetSize(output[0]);
PADDLE_ENFORCE_GT(size,
0,
::common::errors::Fatal(
"The size of output should be greater than 0."));
float *result = static_cast<float *>(output[0].data.data());
for (size_t i = 0; i < size; i++) {
EXPECT_NEAR(result[i], result_data[i], 1e-3);
}
}
}
TEST(Analyzer_dam, profile) { profile(); }
#ifdef PADDLE_WITH_DNNL
TEST(Analyzer_dam, profile_onednn) { profile(true /* use_onednn */); }
#endif
// Compare result of NativeConfig and AnalysisConfig
void compare(bool use_onednn = false) {
AnalysisConfig cfg;
SetConfig(&cfg);
if (use_onednn) {
cfg.EnableONEDNN();
// Enable all the onednn supported ops except conv3d in dam
std::unordered_set<std::string> op_list = {
"softmax", "elementwise_add", "relu"};
cfg.SetONEDNNOp(op_list);
} else {
cfg.DisableONEDNN();
}
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareNativeAndAnalysis(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg), input_slots_all);
}
TEST(Analyzer_dam, compare_with_dynamic_memory_optim) {
// The small dam will core in CI, but works in local.
if (FLAGS_max_turn_num == 9) {
AnalysisConfig cfg, cfg1;
DataRecord data(FLAGS_infer_data, FLAGS_batch_size);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
// Run the first time to force to update memory cache
SetConfig(&cfg);
cfg.EnableMemoryOptim();
CompareNativeAndAnalysis(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all);
}
}
TEST(Analyzer_dam, compare) { compare(); }
#ifdef PADDLE_WITH_DNNL
TEST(Analyzer_dam, compare_onednn) { compare(true /* use_onednn */); }
#endif
// Compare Deterministic result
TEST(Analyzer_dam, compare_determine) {
AnalysisConfig cfg;
SetConfig(&cfg);
cfg.DisableONEDNN();
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareDeterministic(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all);
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,137 @@
/* Copyright (c) 2020 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 <gtest/gtest.h>
#include <fstream>
#include <iostream>
#include "test/cpp/inference/api/tester_helper.h"
PD_DEFINE_string(infer_shape, "", "data shape file");
PD_DEFINE_int32(sample, 20, "number of sample");
namespace paddle {
namespace inference {
namespace analysis {
struct Record {
std::vector<float> data;
std::vector<int32_t> shape;
};
Record ProcessALine(const std::string &line, const std::string &shape_line) {
VLOG(3) << "process a line";
std::vector<std::string> columns;
Record record;
std::vector<std::string> data_strs;
split(line, ' ', &data_strs);
for (auto &d : data_strs) {
record.data.push_back(std::stof(d));
}
std::vector<std::string> shape_strs;
split(shape_line, ' ', &shape_strs);
for (auto &s : shape_strs) {
record.shape.push_back(std::stoi(s));
}
return record;
}
void SetConfig(AnalysisConfig *cfg) {
cfg->SetModel(FLAGS_infer_model + "/model", FLAGS_infer_model + "/params");
cfg->DisableGpu();
cfg->SwitchIrDebug();
cfg->SwitchSpecifyInputNames(false);
cfg->SetCpuMathLibraryNumThreads(FLAGS_cpu_num_threads);
}
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs,
const std::string &line,
const std::string &shape_line) {
auto record = ProcessALine(line, shape_line);
PaddleTensor input;
input.shape = record.shape;
input.dtype = PaddleDType::FLOAT32;
size_t input_size = record.data.size() * sizeof(float);
input.data.Resize(input_size);
memcpy(input.data.data(), record.data.data(), input_size);
std::vector<PaddleTensor> input_slots;
input_slots.assign({input});
(*inputs).emplace_back(input_slots);
}
void profile(int cache_capacity = 1) {
AnalysisConfig cfg;
SetConfig(&cfg);
cfg.EnableONEDNN();
cfg.SetOnednnCacheCapacity(cache_capacity);
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<std::vector<PaddleTensor>> input_slots_all;
Timer run_timer;
double elapsed_time = 0;
int num_times = FLAGS_repeat;
int sample = FLAGS_sample;
auto predictor = CreatePaddlePredictor<AnalysisConfig>(cfg);
outputs.resize(sample);
std::vector<std::thread> threads;
std::ifstream file(FLAGS_infer_data);
std::ifstream infer_file(FLAGS_infer_shape);
std::string line;
std::string shape_line;
for (int i = 0; i < sample; i++) {
threads.emplace_back([&, i]() {
std::getline(file, line);
std::getline(infer_file, shape_line);
SetInput(&input_slots_all, line, shape_line);
run_timer.tic();
predictor->Run(input_slots_all[0], &outputs[0], FLAGS_batch_size);
elapsed_time += run_timer.toc();
});
threads[0].join();
threads.clear();
std::vector<std::vector<PaddleTensor>>().swap(input_slots_all);
}
file.close();
infer_file.close();
auto batch_latency = elapsed_time / (sample * num_times);
PrintTime(FLAGS_batch_size,
num_times,
FLAGS_num_threads,
0,
batch_latency,
sample,
VarType::FP32);
}
#ifdef PADDLE_WITH_DNNL
TEST(Analyzer_detect, profile_onednn) {
profile(5 /* cache_capacity */);
profile(10 /* cache_capacity */);
}
#endif
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,67 @@
// Copyright (c) 2023 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 "gtest/gtest.h"
#include "paddle/fluid/framework/block_desc.h"
#include "paddle/fluid/framework/op_desc.h"
#include "paddle/fluid/framework/program_desc.h"
#include "paddle/fluid/framework/scope.h"
#include "paddle/fluid/inference/utils/singleton.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
TEST(test_dist_model_xpu, dist_model_xpu) {
std::cout << "Analysis Predictor DistModel XPU test." << std::endl;
AnalysisConfig config;
config.SetModel(FLAGS_infer_model + "/__model__",
FLAGS_infer_model + "/__params__");
config.EnableXpu();
config.SetXpuDeviceId(0);
auto predictor = paddle_infer::CreatePredictor(config);
int batch_size = 1;
int channels = 1;
int height = 48;
int width = 512;
int nums = batch_size * channels * height * width;
std::cout << "Created predictor." << std::endl;
float* input = new float[nums];
for (int i = 0; i < nums; ++i) input[i] = 0;
auto input_names = predictor->GetInputNames();
auto input_t = predictor->GetInputHandle(input_names[0]);
input_t->Reshape({batch_size, channels, height, width});
input_t->CopyFromCpu(input);
std::cout << "Input data." << std::endl;
predictor->Run();
std::cout << "Zero Copy Run." << std::endl;
std::vector<float> out_data;
auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputHandle(output_names[0]);
std::vector<int> output_shape = output_t->shape();
int out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
out_data.resize(out_num);
output_t->CopyToCpu(out_data.data());
std::cout << "Output data." << std::endl;
delete[] input;
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,99 @@
/* 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 <fstream>
#include <iostream>
#include "test/cpp/inference/api/tester_helper.h"
PD_DEFINE_bool(disable_onednn_fc, false, "Disable usage of ONE-DNN's FC op");
namespace paddle {
namespace inference {
namespace analysis {
void SetConfig(AnalysisConfig *cfg) {
cfg->SetModel(FLAGS_infer_model + "/model", FLAGS_infer_model + "/params");
cfg->DisableGpu();
cfg->SwitchIrOptim();
cfg->SwitchSpecifyInputNames();
cfg->SetCpuMathLibraryNumThreads(FLAGS_cpu_num_threads);
cfg->DeletePass("constant_folding_pass");
}
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
SetFakeImageInput(inputs, FLAGS_infer_model);
}
// Easy for profiling independently.
void profile(bool use_onednn = false) {
AnalysisConfig cfg;
SetConfig(&cfg);
if (use_onednn) {
cfg.EnableONEDNN();
if (FLAGS_disable_onednn_fc) {
cfg.DisableOnednnFcPasses();
}
}
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all,
&outputs,
FLAGS_num_threads);
}
TEST(Analyzer_resnet50, profile) { profile(); }
#ifdef PADDLE_WITH_DNNL
TEST(Analyzer_resnet50, profile_onednn) { profile(true /* use_onednn */); }
#endif
// Compare result of NativeConfig and AnalysisConfig
void compare(bool use_onednn = false) {
AnalysisConfig cfg;
SetConfig(&cfg);
if (use_onednn) {
cfg.EnableONEDNN();
if (FLAGS_disable_onednn_fc) {
cfg.DisableOnednnFcPasses();
}
}
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareNativeAndAnalysis(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg), input_slots_all);
}
TEST(Analyzer_resnet50, compare) { compare(); }
#ifdef PADDLE_WITH_DNNL
TEST(Analyzer_resnet50, compare_onednn) { compare(true /* use_onednn */); }
#endif
// Compare Deterministic result
TEST(Analyzer_resnet50, compare_determine) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareDeterministic(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all);
}
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,191 @@
// 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 "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
struct DataRecord {
std::vector<int64_t> data;
std::vector<size_t> lod;
// for dataset and nextbatch
size_t batch_iter{0};
std::vector<std::vector<size_t>> batched_lods;
std::vector<std::vector<int64_t>> batched_datas;
std::vector<std::vector<int64_t>> datasets;
DataRecord() : data(), lod(), batched_lods(), batched_datas(), datasets() {}
explicit DataRecord(const std::string &path, int batch_size = 1)
: data(), lod(), batched_lods(), batched_datas(), datasets() {
Load(path);
Prepare(batch_size);
batch_iter = 0;
}
void Load(const std::string &path) {
std::ifstream file(path);
std::string line;
int num_lines = 0;
datasets.resize(0);
while (std::getline(file, line)) {
num_lines++;
std::vector<std::string> data;
split(line, ';', &data);
std::vector<int64_t> words_ids;
split_to_int64(data[1], ' ', &words_ids);
datasets.emplace_back(words_ids);
}
}
void Prepare(int bs) {
if (bs == 1) {
batched_datas = datasets;
for (auto one_sentence : datasets) {
batched_lods.push_back({0, one_sentence.size()});
}
} else {
std::vector<int64_t> one_batch;
std::vector<size_t> lod{0};
int bs_id = 0;
for (auto one_sentence : datasets) {
bs_id++;
one_batch.insert(
one_batch.end(), one_sentence.begin(), one_sentence.end());
lod.push_back(lod.back() + one_sentence.size());
if (bs_id == bs) {
bs_id = 0;
batched_datas.push_back(one_batch);
batched_lods.push_back(lod);
one_batch.clear();
one_batch.resize(0);
lod.clear();
lod.resize(0);
lod.push_back(0);
}
}
if (!one_batch.empty()) {
batched_datas.push_back(one_batch);
batched_lods.push_back(lod);
}
}
}
DataRecord NextBatch() {
DataRecord data;
data.data = batched_datas[batch_iter];
data.lod = batched_lods[batch_iter];
batch_iter++;
if (batch_iter >= batched_datas.size()) {
batch_iter = 0;
}
return data;
}
};
void GetOneBatch(std::vector<PaddleTensor> *input_slots,
DataRecord *data,
int batch_size) {
auto one_batch = data->NextBatch();
PaddleTensor input_tensor;
input_tensor.name = "word";
input_tensor.dtype = PaddleDType::INT64;
TensorAssignData<int64_t>(&input_tensor, {one_batch.data}, one_batch.lod);
PADDLE_ENFORCE_EQ(
batch_size,
static_cast<int>(one_batch.lod.size() - 1),
::common::errors::Fatal("The lod size of one batch is invalid."));
input_slots->assign({input_tensor});
}
void SetConfig(AnalysisConfig *cfg) {
cfg->SetModel(FLAGS_infer_model);
cfg->DisableGpu();
cfg->SwitchSpecifyInputNames();
cfg->SwitchIrOptim();
}
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
DataRecord data(FLAGS_infer_data, FLAGS_batch_size);
std::vector<PaddleTensor> input_slots;
int epoch = FLAGS_test_all_data ? data.batched_datas.size() : 1;
LOG(INFO) << "number of samples: " << epoch;
for (int bid = 0; bid < epoch; ++bid) {
GetOneBatch(&input_slots, &data, FLAGS_batch_size);
(*inputs).emplace_back(input_slots);
}
}
// Easy for profiling independently.
TEST(Analyzer_LAC, profile) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all,
&outputs,
FLAGS_num_threads);
if (FLAGS_num_threads == 1 && !FLAGS_test_all_data) {
// the first inference result
const std::array<int64_t, 47> lac_ref_data = {
24, 25, 25, 25, 38, 30, 31, 14, 15, 44, 24, 25, 25, 25, 25, 25,
44, 24, 25, 25, 25, 36, 42, 43, 44, 14, 15, 44, 14, 15, 44, 14,
15, 44, 38, 39, 14, 15, 44, 22, 23, 23, 23, 23, 23, 23, 23};
PADDLE_ENFORCE_GT(outputs.size(),
0,
::common::errors::Fatal(
"The size of output should be greater than 0."));
auto output = outputs.back();
PADDLE_ENFORCE_EQ(
output.size(),
1UL,
::common::errors::Fatal("The size of output should be equal to 1."));
size_t size = GetSize(output[0]);
size_t batch1_size = sizeof(lac_ref_data) / sizeof(int64_t);
PADDLE_ENFORCE_GE(size,
batch1_size,
::common::errors::Fatal("The size of batch is invalid."));
int64_t *pdata = static_cast<int64_t *>(output[0].data.data());
for (size_t i = 0; i < batch1_size; ++i) {
EXPECT_EQ(pdata[i], lac_ref_data[i]);
}
}
}
// Compare result of NativeConfig and AnalysisConfig
TEST(Analyzer_LAC, compare) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareNativeAndAnalysis(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg), input_slots_all);
}
// Compare Deterministic result
TEST(Analyzer_LAC, compare_determine) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareDeterministic(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all);
}
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,115 @@
// Copyright (c) 2020 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 <random>
#include "paddle/fluid/framework/transfer_scope_cache.h"
#include "test/cpp/inference/api/tester_helper.h"
// Here add missing commands
PD_DEFINE_string(infer_model2, "", "model path");
PD_DEFINE_string(infer_model3, "", "model path");
namespace paddle {
namespace inference {
// Shape of Input to models
const int N = 1, C = 3, H = 224, W = 224;
void SetConfig(AnalysisConfig* config, const std::string& infer_model) {
config->SetModel(infer_model + "/__model__", infer_model + "/__params__");
config->DisableFCPadding();
config->SwitchSpecifyInputNames(true);
}
std::unique_ptr<PaddlePredictor> InitializePredictor(
const std::string& infer_model,
const std::vector<float>& data,
bool use_onednn) {
AnalysisConfig cfg;
SetConfig(&cfg, infer_model);
if (use_onednn) {
cfg.EnableONEDNN();
}
auto predictor = ::paddle::CreatePaddlePredictor<AnalysisConfig>(cfg);
auto input_name = predictor->GetInputNames()[0];
auto input = predictor->GetInputTensor(input_name);
std::vector<int> shape{N, C, H, W};
input->Reshape(std::move(shape));
input->copy_from_cpu(data.data());
return predictor;
}
// Compare result of NativeConfig and AnalysisConfig
void compare(bool use_onednn = false) {
// Create Input to models
std::vector<float> data(N * C * H * W);
std::default_random_engine re{1234};
std::uniform_real_distribution<float> sampler{0.0, 1.0};
for (auto& v : data) {
v = sampler(re);
}
// Initialize Models predictors
auto predictor_1 = InitializePredictor(FLAGS_infer_model, data, use_onednn);
auto predictor_xx = InitializePredictor(FLAGS_infer_model2, data, use_onednn);
auto predictor_3 = InitializePredictor(FLAGS_infer_model3, data, use_onednn);
// Run single xx model
predictor_xx->ZeroCopyRun();
auto output =
predictor_xx->GetOutputTensor(predictor_xx->GetOutputNames()[0]);
auto output_shape = output->shape();
int numel = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
std::vector<float> xx_output(numel);
output->copy_to_cpu(xx_output.data());
// Initialize xx model's predictor to trigger oneDNN cache clearing
predictor_xx = InitializePredictor(FLAGS_infer_model2, data, use_onednn);
// Run sequence of models
predictor_1->ZeroCopyRun();
predictor_xx->ZeroCopyRun();
predictor_3->ZeroCopyRun();
// Get again output of xx model , but when all three models were executed
std::vector<float> xx2_output(numel);
output = predictor_xx->GetOutputTensor(predictor_xx->GetOutputNames()[0]);
output->copy_to_cpu(xx2_output.data());
// compare results
auto result = std::equal(
xx_output.begin(),
xx_output.end(),
xx2_output.begin(),
[](const float& l, const float& r) { return fabs(l - r) < 1e-4; });
PADDLE_ENFORCE_EQ(
result,
true,
::common::errors::Fatal("Results of model run independently "
"differs from results of the same model "
"run as a sequence of models"));
}
TEST(Analyzer_mmp, compare) { compare(); }
#ifdef PADDLE_WITH_DNNL
TEST(Analyzer_mmp, compare_onednn) { compare(true /* use_onednn */); }
#endif
} // namespace inference
} // namespace paddle
@@ -0,0 +1,175 @@
// 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 "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
struct DataRecord {
std::vector<std::vector<int64_t>> word, mention;
std::vector<size_t> lod; // two inputs have the same lod info.
size_t batch_iter{0}, batch_size{1}, num_samples; // total number of samples
DataRecord() : word(), mention(), lod(), num_samples(0) {}
explicit DataRecord(const std::string &path, int batch_size = 1)
: word(), mention(), lod(), batch_size(batch_size), num_samples(0) {
Load(path);
}
DataRecord NextBatch() {
DataRecord data;
size_t batch_end = batch_iter + batch_size;
// NOTE skip the final batch, if no enough data is provided.
if (batch_end <= word.size()) {
GetInputPerBatch(word, &data.word, &data.lod, batch_iter, batch_end);
GetInputPerBatch(
mention, &data.mention, &data.lod, batch_iter, batch_end);
}
batch_iter += batch_size;
return data;
}
void Load(const std::string &path) {
std::ifstream file(path);
std::string line;
int num_lines = 0;
while (std::getline(file, line)) {
num_lines++;
std::vector<std::string> data;
split(line, ';', &data);
// load word data
std::vector<int64_t> word_data;
split_to_int64(data[1], ' ', &word_data);
// load mention data
std::vector<int64_t> mention_data;
split_to_int64(data[3], ' ', &mention_data);
word.push_back(std::move(word_data));
mention.push_back(std::move(mention_data));
}
num_samples = num_lines;
}
};
void PrepareInputs(std::vector<PaddleTensor> *input_slots, DataRecord *data) {
PaddleTensor lod_word_tensor, lod_mention_tensor;
lod_word_tensor.name = "word";
lod_mention_tensor.name = "mention";
auto one_batch = data->NextBatch();
// assign data
TensorAssignData<int64_t>(&lod_word_tensor, one_batch.word, one_batch.lod);
TensorAssignData<int64_t>(
&lod_mention_tensor, one_batch.mention, one_batch.lod);
// Set inputs.
input_slots->assign({lod_word_tensor, lod_mention_tensor});
for (auto &tensor : *input_slots) {
tensor.dtype = PaddleDType::INT64;
}
}
void SetConfig(AnalysisConfig *cfg, bool memory_load = false) {
if (memory_load) {
std::string buffer_prog, buffer_param;
ReadBinaryFile(FLAGS_infer_model + "/__model__", &buffer_prog);
ReadBinaryFile(FLAGS_infer_model + "/param", &buffer_param);
cfg->SetModelBuffer(&buffer_prog[0],
buffer_prog.size(),
&buffer_param[0],
buffer_param.size());
} else {
cfg->SetModel(FLAGS_infer_model + "/__model__",
FLAGS_infer_model + "/param");
}
cfg->DisableGpu();
cfg->SwitchSpecifyInputNames();
cfg->SwitchIrOptim();
}
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
DataRecord data(FLAGS_infer_data, FLAGS_batch_size);
std::vector<PaddleTensor> input_slots;
int epoch =
FLAGS_test_all_data ? data.num_samples / FLAGS_batch_size : 1; // NOLINT
LOG(INFO) << "number of samples: " << epoch * FLAGS_batch_size;
for (int bid = 0; bid < epoch; ++bid) {
PrepareInputs(&input_slots, &data);
(*inputs).emplace_back(input_slots);
}
}
// Easy for profiling independently.
void profile(bool memory_load = false) {
AnalysisConfig cfg;
SetConfig(&cfg, memory_load);
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all,
&outputs,
FLAGS_num_threads);
if (FLAGS_num_threads == 1 && !FLAGS_test_all_data) {
// the first inference result
const std::array<int, 11> chinese_ner_result_data = {
30, 45, 41, 48, 17, 26, 48, 39, 38, 16, 25};
PADDLE_ENFORCE_GT(
outputs.size(),
0,
common::errors::Fatal("The size of output should be greater than 0."));
auto output = outputs.back();
PADDLE_ENFORCE_EQ(
output.size(),
1UL,
common::errors::Fatal("The size of output should be equal to 1."));
size_t size = GetSize(output[0]);
PADDLE_ENFORCE_GT(
size,
0,
common::errors::Fatal("The size of output should be greater than 0."));
int64_t *result = static_cast<int64_t *>(output[0].data.data());
for (size_t i = 0; i < std::min<size_t>(11, size); i++) {
EXPECT_EQ(result[i], chinese_ner_result_data[i]);
}
}
}
TEST(Analyzer_Chinese_ner, profile) { profile(); }
TEST(Analyzer_Chinese_ner, profile_memory_load) {
profile(true /* memory_load */);
}
// Compare result of NativeConfig and AnalysisConfig
TEST(Analyzer_Chinese_ner, compare) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareNativeAndAnalysis(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg), input_slots_all);
}
// Compare Deterministic result
TEST(Analyzer_Chinese_ner, compare_determine) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareDeterministic(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all);
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,72 @@
/* 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 <fstream>
#include <iostream>
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
void SetConfig(AnalysisConfig *cfg) {
cfg->SetModel(FLAGS_infer_model + "/inference.pdmodel",
FLAGS_infer_model + "/inference.pdiparams");
cfg->DisableGpu();
cfg->SwitchIrOptim();
cfg->EnableOpenVINOEngine(AnalysisConfig::Precision::kFloat32);
if (cfg->openvino_engine_enabled()) {
cfg->SetCpuMathLibraryNumThreads(FLAGS_cpu_num_threads);
}
}
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
SetFakeImageInput(inputs,
FLAGS_infer_model,
true,
"inference.pdmodel",
"inference.pdiparams");
}
// Easy for profiling independently.
void profile() {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all,
&outputs,
FLAGS_num_threads);
}
TEST(Analyzer_openvino_resnet50, profile) { profile(); }
#ifdef PADDLE_WITH_OPENVINO
TEST(Analyzer_openvino_resnet50, compare_determine) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareDeterministic(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all);
}
#endif
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,205 @@
// 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 "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
struct DataRecord {
std::vector<std::vector<int64_t>> query_basic, query_phrase, title_basic,
title_phrase;
std::vector<size_t> lod1, lod2, lod3, lod4;
size_t batch_iter{0}, batch_size{1}, num_samples; // total number of samples
DataRecord() = default;
explicit DataRecord(const std::string &path, int batch_size = 1)
: batch_size(batch_size) {
Load(path);
}
DataRecord NextBatch() {
DataRecord data;
size_t batch_end = batch_iter + batch_size;
// NOTE skip the final batch, if no enough data is provided.
if (batch_end <= query_basic.size()) {
GetInputPerBatch(
query_basic, &data.query_basic, &data.lod1, batch_iter, batch_end);
GetInputPerBatch(
query_phrase, &data.query_phrase, &data.lod2, batch_iter, batch_end);
GetInputPerBatch(
title_basic, &data.title_basic, &data.lod3, batch_iter, batch_end);
GetInputPerBatch(
title_phrase, &data.title_phrase, &data.lod4, batch_iter, batch_end);
}
batch_iter += batch_size;
return data;
}
void Load(const std::string &path) {
std::ifstream file(path);
std::string line;
int num_lines = 0;
while (std::getline(file, line)) {
std::vector<std::string> data;
split(line, ';', &data);
// load query data
std::vector<int64_t> query_basic_data;
split_to_int64(data[1], ' ', &query_basic_data);
std::vector<int64_t> query_phrase_data;
split_to_int64(data[2], ' ', &query_phrase_data);
// load title data
std::vector<int64_t> title_basic_data;
split_to_int64(data[3], ' ', &title_basic_data);
std::vector<int64_t> title_phrase_data;
split_to_int64(data[4], ' ', &title_phrase_data);
// filter the empty data
bool flag =
data[1].size() && data[2].size() && data[3].size() && data[4].size();
if (flag) {
query_basic.push_back(std::move(query_basic_data));
query_phrase.push_back(std::move(query_phrase_data));
title_basic.push_back(std::move(title_basic_data));
title_phrase.push_back(std::move(title_phrase_data));
num_lines++;
}
}
num_samples = num_lines;
}
};
void PrepareInputs(std::vector<PaddleTensor> *input_slots,
DataRecord *data,
int batch_size) {
PaddleTensor query_basic_tensor, query_phrase_tensor, title_basic_tensor,
title_phrase_tensor;
query_basic_tensor.name = "query_basic";
query_phrase_tensor.name = "query_phrase";
title_basic_tensor.name = "pos_title_basic";
title_phrase_tensor.name = "pos_title_phrase";
auto one_batch = data->NextBatch();
// assign data
TensorAssignData<int64_t>(
&query_basic_tensor, one_batch.query_basic, one_batch.lod1);
TensorAssignData<int64_t>(
&query_phrase_tensor, one_batch.query_phrase, one_batch.lod2);
TensorAssignData<int64_t>(
&title_basic_tensor, one_batch.title_basic, one_batch.lod3);
TensorAssignData<int64_t>(
&title_phrase_tensor, one_batch.title_phrase, one_batch.lod4);
// Set inputs.
input_slots->assign({query_basic_tensor,
query_phrase_tensor,
title_basic_tensor,
title_phrase_tensor});
for (auto &tensor : *input_slots) {
tensor.dtype = PaddleDType::INT64;
}
}
void SetConfig(AnalysisConfig *cfg) {
cfg->SetModel(FLAGS_infer_model);
cfg->DisableGpu();
cfg->SwitchSpecifyInputNames();
cfg->SwitchIrOptim();
cfg->SetCpuMathLibraryNumThreads(FLAGS_cpu_num_threads);
}
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
DataRecord data(FLAGS_infer_data, FLAGS_batch_size);
std::vector<PaddleTensor> input_slots;
int epoch = FLAGS_test_all_data ? data.num_samples / FLAGS_batch_size : 1;
LOG(INFO) << "number of samples: " << epoch * FLAGS_batch_size;
for (int bid = 0; bid < epoch; ++bid) {
PrepareInputs(&input_slots, &data, FLAGS_batch_size);
(*inputs).emplace_back(input_slots);
}
}
// Easy for profiling independently.
TEST(Analyzer_Pyramid_DNN, profile) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all,
&outputs,
FLAGS_num_threads);
if (FLAGS_num_threads == 1 && !FLAGS_test_all_data && !FLAGS_zero_copy) {
PADDLE_ENFORCE_GT(
outputs.size(),
0,
common::errors::Fatal("The size of output should be greater than 0."));
auto output = outputs.back();
PADDLE_ENFORCE_EQ(
output.size(),
1UL,
common::errors::Fatal("The size of output should be equal to 1."));
size_t size = GetSize(output[0]);
PADDLE_ENFORCE_GT(
size,
0,
common::errors::Fatal("The size of output should be greater than 0."));
float *result = static_cast<float *>(output[0].data.data());
// output is probability, which is in (0, 1).
for (size_t i = 0; i < size; i++) {
EXPECT_GT(result[i], 0);
EXPECT_LT(result[i], 1);
}
}
}
// Compare result of NativeConfig and AnalysisConfig
TEST(Analyzer_Pyramid_DNN, compare) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareNativeAndAnalysis(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg), input_slots_all);
}
// Compare result of AnalysisConfig and AnalysisConfig + ZeroCopy
TEST(Analyzer_Pyramid_DNN, compare_zero_copy) {
AnalysisConfig cfg;
SetConfig(&cfg);
AnalysisConfig cfg1;
SetConfig(&cfg1);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
std::vector<std::string> outputs_name;
outputs_name.emplace_back("cos_sim_2.tmp_0");
CompareAnalysisAndZeroCopy(reinterpret_cast<PaddlePredictor::Config *>(&cfg),
reinterpret_cast<PaddlePredictor::Config *>(&cfg1),
input_slots_all,
outputs_name);
}
// Compare Deterministic result
TEST(Analyzer_Pyramid_DNN, compare_determine) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareDeterministic(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all);
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,143 @@
/* 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. */
#include <fstream>
#include <iostream>
#include "paddle/fluid/inference/api/paddle_analysis_config.h"
#include "test/cpp/inference/api/tester_helper.h"
PD_DEFINE_bool(enable_onednn, true, "Enable ONEDNN");
namespace paddle {
namespace inference {
namespace analysis {
void SetConfig(AnalysisConfig *cfg, std::string model_path) {
cfg->SetModel(model_path);
cfg->DisableGpu();
cfg->SwitchIrOptim(true);
cfg->SetCpuMathLibraryNumThreads(FLAGS_cpu_num_threads);
cfg->EnableNewIR();
cfg->EnableNewExecutor();
cfg->SetOptimizationLevel(3);
if (FLAGS_enable_onednn) cfg->EnableONEDNN();
}
template <typename T>
class TensorReader {
public:
TensorReader(std::ifstream &file,
size_t beginning_offset,
std::vector<int> shape,
std::string name)
: file_(file),
position_(beginning_offset),
shape_(shape),
name_(name),
numel_(0) {
numel_ = std::accumulate(
shape_.begin(), shape_.end(), size_t{1}, std::multiplies<size_t>());
}
PaddleTensor NextBatch() {
PaddleTensor tensor;
tensor.name = name_;
tensor.shape = shape_;
tensor.dtype = GetPaddleDType<T>();
tensor.data.Resize(numel_ * sizeof(T));
file_.seekg(position_);
file_.read(static_cast<char *>(tensor.data.data()), numel_ * sizeof(T));
position_ = file_.tellg();
if (file_.eof()) LOG(ERROR) << name_ << ": reached end of stream";
if (file_.fail())
throw std::runtime_error(name_ + ": failed reading file.");
return tensor;
}
protected:
std::ifstream &file_;
size_t position_;
std::vector<int> shape_;
std::string name_;
size_t numel_;
};
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs,
bool with_accuracy_layer = FLAGS_with_accuracy_layer,
int32_t batch_size = FLAGS_batch_size) {
std::ifstream file(FLAGS_infer_data, std::ios::binary);
if (!file) {
FAIL() << "Couldn't open file: " << FLAGS_infer_data;
}
int64_t total_images{0};
file.read(reinterpret_cast<char *>(&total_images), sizeof(total_images));
LOG(INFO) << "Total images in file: " << total_images;
std::vector<int> image_batch_shape{batch_size, 3, 224, 224};
std::vector<int> label_batch_shape{batch_size, 1};
auto images_offset_in_file = static_cast<size_t>(file.tellg());
TensorReader<float> image_reader(
file, images_offset_in_file, image_batch_shape, "image");
auto iterations_max = total_images / batch_size;
auto iterations = iterations_max;
if (FLAGS_iterations > 0 && FLAGS_iterations < iterations_max) {
iterations = FLAGS_iterations;
}
auto labels_offset_in_file =
images_offset_in_file + sizeof(float) * total_images * 3 * 224 * 224;
TensorReader<int64_t> label_reader(
file, labels_offset_in_file, label_batch_shape, "label");
for (auto i = 0; i < iterations; i++) {
auto images = image_reader.NextBatch();
std::vector<PaddleTensor> tmp_vec;
tmp_vec.push_back(std::move(images));
if (with_accuracy_layer) {
auto labels = label_reader.NextBatch();
tmp_vec.push_back(std::move(labels));
}
inputs->push_back(std::move(tmp_vec));
}
}
TEST(Analyzer_quant_image_classification, quantization) {
AnalysisConfig fp32_cfg;
SetConfig(&fp32_cfg, FLAGS_fp32_model);
fp32_cfg.EnableONEDNN();
AnalysisConfig int8_cfg;
SetConfig(&int8_cfg, FLAGS_int8_model);
if (FLAGS_enable_int8_qat) int8_cfg.EnableOnednnInt8();
// read data from file and prepare batches with test data
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
// 0 is avg_cost, 1 is top1_accuracy, 2 is top5_accuracy or mAP
CompareAnalysisAndAnalysis(
&fp32_cfg, &int8_cfg, input_slots_all, FLAGS_with_accuracy_layer, 1);
}
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,325 @@
// 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 "test/cpp/inference/api/tester_helper.h"
#include "paddle/common/enforce.h"
PD_DEFINE_bool(with_precision_check, true, "turn on test");
namespace paddle {
namespace inference {
using namespace framework; // NOLINT
struct DataRecord {
std::vector<std::vector<std::vector<float>>> link_step_data_all;
std::vector<std::vector<float>> week_data_all, minute_data_all;
std::vector<size_t> lod1, lod2, lod3;
std::vector<std::vector<float>> rnn_link_data, rnn_week_datas,
rnn_minute_datas;
size_t num_samples; // total number of samples
size_t batch_iter{0};
size_t batch_size{1};
DataRecord() = default;
explicit DataRecord(const std::string &path, int batch_size = 1)
: batch_size(batch_size) {
Load(path);
}
DataRecord NextBatch() {
DataRecord data;
size_t batch_end = batch_iter + batch_size;
// NOTE skip the final batch, if no enough data is provided.
if (batch_end <= link_step_data_all.size()) {
data.link_step_data_all.assign(link_step_data_all.begin() + batch_iter,
link_step_data_all.begin() + batch_end);
data.week_data_all.assign(week_data_all.begin() + batch_iter,
week_data_all.begin() + batch_end);
data.minute_data_all.assign(minute_data_all.begin() + batch_iter,
minute_data_all.begin() + batch_end);
// Prepare LoDs
data.lod1.push_back(0);
data.lod2.push_back(0);
data.lod3.push_back(0);
PADDLE_ENFORCE_EQ(!data.link_step_data_all.empty(),
true,
common::errors::InvalidArgument(
"link_step_data_all should not be empty."));
PADDLE_ENFORCE_EQ(!data.week_data_all.empty(),
true,
common::errors::InvalidArgument(
"week_data_all should not be empty."));
PADDLE_ENFORCE_EQ(!data.minute_data_all.empty(),
true,
common::errors::InvalidArgument(
"minute_data_all should not be empty."));
PADDLE_ENFORCE_EQ(
data.link_step_data_all.size(),
data.week_data_all.size(),
platform::errors::InvalidArgument(
"The value of data.link_step_data_all.size() is not equal to the "
"value of data.week_data_all.size()."))
PADDLE_ENFORCE_EQ(
data.minute_data_all.size(),
data.link_step_data_all.size(),
platform::errors::InvalidArgument(
"The value of data.minute_data_all.size() is not equal to the "
"value of data.link_step_data_all.size()."))
for (size_t j = 0; j < data.link_step_data_all.size(); j++) {
for (const auto &d : data.link_step_data_all[j]) {
data.rnn_link_data.push_back(d);
}
data.rnn_week_datas.push_back(data.week_data_all[j]);
data.rnn_minute_datas.push_back(data.minute_data_all[j]);
// calculate lod
data.lod1.push_back(data.lod1.back() +
data.link_step_data_all[j].size());
data.lod3.push_back(data.lod3.back() + 1);
for (size_t i = 1; i < data.link_step_data_all[j].size() + 1; i++) {
data.lod2.push_back(data.lod2.back() +
data.link_step_data_all[j].size());
}
}
}
batch_iter += batch_size;
return data;
}
void Load(const std::string &path) {
std::ifstream file(path);
std::string line;
int num_lines = 0;
while (std::getline(file, line)) {
num_lines++;
std::vector<std::string> data;
split(line, ':', &data);
std::vector<std::vector<float>> link_step_data;
std::vector<std::string> link_datas;
split(data[0], '|', &link_datas);
for (auto &step_data : link_datas) {
std::vector<float> tmp;
split_to_float(step_data, ',', &tmp);
link_step_data.push_back(tmp);
}
// load week data
std::vector<float> week_data;
split_to_float(data[2], ',', &week_data);
// load minute data
std::vector<float> minute_data;
split_to_float(data[1], ',', &minute_data);
link_step_data_all.push_back(std::move(link_step_data));
week_data_all.push_back(std::move(week_data));
minute_data_all.push_back(std::move(minute_data));
}
num_samples = num_lines;
}
};
void PrepareInputs(std::vector<PaddleTensor> *input_slots,
DataRecord *data,
int batch_size) {
PaddleTensor lod_attention_tensor, init_zero_tensor, lod_tensor_tensor,
week_tensor, minute_tensor;
lod_attention_tensor.name = "data_lod_attention";
init_zero_tensor.name = "cell_init";
lod_tensor_tensor.name = "data";
week_tensor.name = "week";
minute_tensor.name = "minute";
auto one_batch = data->NextBatch();
std::vector<int> rnn_link_data_shape(
{static_cast<int>(one_batch.rnn_link_data.size()),
static_cast<int>(one_batch.rnn_link_data.front().size())});
lod_attention_tensor.shape.assign({1, 2});
lod_attention_tensor.lod.assign({one_batch.lod1, one_batch.lod2});
init_zero_tensor.shape.assign({batch_size, 15});
init_zero_tensor.lod.assign({one_batch.lod3});
lod_tensor_tensor.shape = rnn_link_data_shape;
lod_tensor_tensor.lod.assign({one_batch.lod1});
week_tensor.shape.assign(
{static_cast<int>(one_batch.rnn_week_datas.size()),
static_cast<int>(one_batch.rnn_week_datas.front().size())});
week_tensor.lod.assign({one_batch.lod3});
minute_tensor.shape.assign(
{static_cast<int>(one_batch.rnn_minute_datas.size()),
static_cast<int>(one_batch.rnn_minute_datas.front().size())});
minute_tensor.lod.assign({one_batch.lod3});
// assign data
TensorAssignData<float>(&lod_attention_tensor,
std::vector<std::vector<float>>({{0, 0}}));
std::vector<float> tmp_zeros(batch_size * 15, 0.);
TensorAssignData<float>(&init_zero_tensor, {tmp_zeros});
TensorAssignData<float>(&lod_tensor_tensor, one_batch.rnn_link_data);
TensorAssignData<float>(&week_tensor, one_batch.rnn_week_datas);
TensorAssignData<float>(&minute_tensor, one_batch.rnn_minute_datas);
// Set inputs.
auto init_zero_tensor1 = init_zero_tensor;
init_zero_tensor1.name = "hidden_init";
input_slots->assign({week_tensor,
init_zero_tensor,
minute_tensor,
init_zero_tensor1,
lod_attention_tensor,
lod_tensor_tensor});
for (auto &tensor : *input_slots) {
tensor.dtype = PaddleDType::FLOAT32;
}
}
void PrepareZeroCopyInputs(ZeroCopyTensor *lod_attention_tensor,
ZeroCopyTensor *cell_init_tensor,
ZeroCopyTensor *data_tensor,
ZeroCopyTensor *hidden_init_tensor,
ZeroCopyTensor *week_tensor,
ZeroCopyTensor *minute_tensor,
DataRecord *data_record,
int batch_size) {
auto one_batch = data_record->NextBatch();
std::vector<int> rnn_link_data_shape(
{static_cast<int>(one_batch.rnn_link_data.size()),
static_cast<int>(one_batch.rnn_link_data.front().size())});
lod_attention_tensor->Reshape({1, 2});
lod_attention_tensor->SetLoD({one_batch.lod1, one_batch.lod2});
cell_init_tensor->Reshape({batch_size, 15});
cell_init_tensor->SetLoD({one_batch.lod3});
hidden_init_tensor->Reshape({batch_size, 15});
hidden_init_tensor->SetLoD({one_batch.lod3});
data_tensor->Reshape(rnn_link_data_shape);
data_tensor->SetLoD({one_batch.lod1});
week_tensor->Reshape(
{static_cast<int>(one_batch.rnn_week_datas.size()),
static_cast<int>(one_batch.rnn_week_datas.front().size())});
week_tensor->SetLoD({one_batch.lod3});
minute_tensor->Reshape(
{static_cast<int>(one_batch.rnn_minute_datas.size()),
static_cast<int>(one_batch.rnn_minute_datas.front().size())});
minute_tensor->SetLoD({one_batch.lod3});
// assign data
std::array<float, 2> arr0 = {0, 0};
std::vector<float> zeros(batch_size * 15, 0);
std::copy_n(arr0.data(),
2,
lod_attention_tensor->mutable_data<float>(PaddlePlace::kCPU));
std::copy_n(
arr0.data(), 2, data_tensor->mutable_data<float>(PaddlePlace::kCPU));
std::copy_n(zeros.begin(),
zeros.size(),
cell_init_tensor->mutable_data<float>(PaddlePlace::kCPU));
std::copy_n(zeros.begin(),
zeros.size(),
hidden_init_tensor->mutable_data<float>(PaddlePlace::kCPU));
ZeroCopyTensorAssignData(data_tensor, one_batch.rnn_link_data);
ZeroCopyTensorAssignData(week_tensor, one_batch.rnn_week_datas);
ZeroCopyTensorAssignData(minute_tensor, one_batch.rnn_minute_datas);
}
void SetConfig(AnalysisConfig *cfg) {
cfg->SetModel(FLAGS_infer_model + "/__model__", FLAGS_infer_model + "/param");
cfg->DisableGpu();
cfg->SwitchSpecifyInputNames();
cfg->SwitchIrOptim();
}
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
DataRecord data(FLAGS_infer_data, FLAGS_batch_size);
std::vector<PaddleTensor> input_slots;
int epoch =
FLAGS_test_all_data ? data.num_samples / FLAGS_batch_size : 1; // NOLINT
LOG(INFO) << "number of samples: " << epoch * FLAGS_batch_size;
for (int bid = 0; bid < epoch; ++bid) {
PrepareInputs(&input_slots, &data, FLAGS_batch_size);
(*inputs).emplace_back(input_slots);
}
}
// Easy for profiling independently.
TEST(Analyzer_rnn1, profile) {
AnalysisConfig cfg;
SetConfig(&cfg);
cfg.DisableGpu();
cfg.SwitchIrDebug();
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all,
&outputs,
FLAGS_num_threads);
}
// Compare result of NativeConfig and AnalysisConfig
TEST(Analyzer_rnn1, compare) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareNativeAndAnalysis(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg), input_slots_all);
}
// Compare Deterministic result
TEST(Analyzer_rnn1, compare_determine) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareDeterministic(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all);
}
// Test Multi-Thread.
TEST(Analyzer_rnn1, multi_thread) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all,
&outputs,
2 /* multi_thread */);
}
// Compare result of AnalysisConfig and AnalysisConfig + ZeroCopy
TEST(Analyzer_rnn1, compare_zero_copy) {
AnalysisConfig cfg;
SetConfig(&cfg);
AnalysisConfig cfg1;
SetConfig(&cfg1);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
std::vector<std::string> outputs_name;
outputs_name.emplace_back("final_output.tmp_1");
CompareAnalysisAndZeroCopy(reinterpret_cast<PaddlePredictor::Config *>(&cfg),
reinterpret_cast<PaddlePredictor::Config *>(&cfg1),
input_slots_all,
outputs_name);
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,194 @@
// 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 "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
using namespace framework; // NOLINT
static std::vector<float> result_data;
struct DataRecord {
std::vector<std::vector<std::vector<float>>> link_step_data_all;
std::vector<size_t> lod;
std::vector<std::vector<float>> rnn_link_data;
size_t num_samples; // total number of samples
size_t batch_iter{0};
size_t batch_size{1};
DataRecord() : link_step_data_all(), lod(), rnn_link_data(), num_samples(0) {}
explicit DataRecord(const std::string &path, int batch_size = 1)
: link_step_data_all(),
lod(),
rnn_link_data(),
num_samples(0),
batch_size(batch_size) {
Load(path);
}
DataRecord NextBatch() {
DataRecord data;
size_t batch_end = batch_iter + batch_size;
// NOTE skip the final batch, if no enough data is provided.
if (batch_end <= link_step_data_all.size()) {
data.link_step_data_all.assign(link_step_data_all.begin() + batch_iter,
link_step_data_all.begin() + batch_end);
// Prepare LoDs
data.lod.push_back(0);
PADDLE_ENFORCE_EQ(
!data.link_step_data_all.empty(),
true,
common::errors::InvalidArgument(
"`data.link_step_data_all` is empty, please check"));
for (size_t j = 0; j < data.link_step_data_all.size(); j++) {
for (const auto &d : data.link_step_data_all[j]) {
data.rnn_link_data.push_back(d);
// calculate lod
data.lod.push_back(data.lod.back() + 11);
}
}
}
batch_iter += batch_size;
return data;
}
void Load(const std::string &path) {
std::ifstream file(path);
std::string line;
int num_lines = 0;
result_data.clear();
while (std::getline(file, line)) {
num_lines++;
std::vector<std::string> data;
split(line, ':', &data);
if (num_lines % 2) { // feature
std::vector<std::string> feature_data;
split(data[1], ' ', &feature_data);
std::vector<std::vector<float>> link_step_data;
int feature_count = 1;
std::vector<float> feature;
for (auto &step_data : feature_data) {
std::vector<float> tmp;
split_to_float(step_data, ',', &tmp);
feature.insert(feature.end(), tmp.begin(), tmp.end());
if (feature_count % 11 == 0) { // each sample has 11 features
link_step_data.push_back(feature);
feature.clear();
}
feature_count++;
}
link_step_data_all.push_back(std::move(link_step_data));
} else { // result
std::vector<float> tmp;
split_to_float(data[1], ',', &tmp);
result_data.insert(result_data.end(), tmp.begin(), tmp.end());
}
}
num_samples = num_lines / 2;
}
};
void PrepareInputs(std::vector<PaddleTensor> *input_slots,
DataRecord *data,
int batch_size) {
PaddleTensor feed_tensor;
feed_tensor.name = "feed";
auto one_batch = data->NextBatch();
int token_size = one_batch.rnn_link_data.size();
// each token has 11 features, each feature's dim is 54.
std::vector<int> rnn_link_data_shape({token_size * 11, 54});
feed_tensor.shape = rnn_link_data_shape;
feed_tensor.lod.assign({one_batch.lod});
feed_tensor.dtype = PaddleDType::FLOAT32;
TensorAssignData<float>(&feed_tensor, one_batch.rnn_link_data);
// Set inputs.
input_slots->assign({feed_tensor});
}
void SetConfig(AnalysisConfig *cfg) {
cfg->SetModel(FLAGS_infer_model + "/__model__", FLAGS_infer_model + "/param");
cfg->DisableGpu();
cfg->SwitchSpecifyInputNames();
cfg->SwitchIrOptim();
}
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
DataRecord data(FLAGS_infer_data, FLAGS_batch_size);
std::vector<PaddleTensor> input_slots;
int epoch =
FLAGS_test_all_data ? data.num_samples / FLAGS_batch_size : 1; // NOLINT
LOG(INFO) << "number of samples: " << epoch * FLAGS_batch_size;
for (int bid = 0; bid < epoch; ++bid) {
PrepareInputs(&input_slots, &data, FLAGS_batch_size);
(*inputs).emplace_back(input_slots);
}
}
// Easy for profiling independently.
TEST(Analyzer_rnn2, profile) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all,
&outputs,
FLAGS_num_threads);
if (FLAGS_num_threads == 1 && !FLAGS_test_all_data) {
// the first inference result
PADDLE_ENFORCE_GT(
outputs.size(),
0,
common::errors::Fatal("The size of output should be greater than 0."));
auto output = outputs.back();
PADDLE_ENFORCE_GT(
output.size(),
0,
common::errors::Fatal("The size of output should be greater than 0."));
size_t size = GetSize(output[0]);
PADDLE_ENFORCE_GT(
size,
0,
common::errors::Fatal("The size of output should be greater than 0."));
float *result = static_cast<float *>(output[0].data.data());
for (size_t i = 0; i < size; i++) {
EXPECT_NEAR(result[i], result_data[i], 1e-3);
}
}
}
// Compare result of NativeConfig and AnalysisConfig
TEST(Analyzer_rnn2, compare) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareNativeAndAnalysis(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg), input_slots_all);
}
// Compare Deterministic result
TEST(Analyzer_rnn2, compare_determine) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareDeterministic(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all);
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,194 @@
// 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 "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
struct DataRecord {
std::vector<std::vector<int64_t>> title1, title2, title3, l1;
std::vector<size_t> lod1, lod2, lod3, l1_lod;
size_t batch_iter{0}, batch_size{1}, num_samples; // total number of samples
DataRecord()
: title1(),
title2(),
title3(),
l1(),
lod1(),
lod2(),
lod3(),
l1_lod(),
batch_size(0),
num_samples(0) {}
explicit DataRecord(const std::string &path, int batch_size = 1)
: title1(),
title2(),
title3(),
l1(),
lod1(),
lod2(),
lod3(),
l1_lod(),
batch_size(batch_size),
num_samples(0) {
Load(path);
}
DataRecord NextBatch() {
DataRecord data;
size_t batch_end = batch_iter + batch_size;
// NOTE skip the final batch, if no enough data is provided.
if (batch_end <= title1.size()) {
GetInputPerBatch(title1, &data.title1, &data.lod1, batch_iter, batch_end);
GetInputPerBatch(title2, &data.title2, &data.lod2, batch_iter, batch_end);
GetInputPerBatch(title3, &data.title3, &data.lod3, batch_iter, batch_end);
GetInputPerBatch(l1, &data.l1, &data.l1_lod, batch_iter, batch_end);
}
batch_iter += batch_size;
return data;
}
void Load(const std::string &path) {
std::ifstream file(path);
std::string line;
int num_lines = 0;
while (std::getline(file, line)) {
num_lines++;
std::vector<std::string> data;
split(line, '\t', &data);
PADDLE_ENFORCE_GT(data.size(),
4,
common::errors::Fatal("The size of data is invalid."));
// load title1 data
std::vector<int64_t> title1_data;
split_to_int64(data[0], ' ', &title1_data);
// load title2 data
std::vector<int64_t> title2_data;
split_to_int64(data[1], ' ', &title2_data);
// load title3 data
std::vector<int64_t> title3_data;
split_to_int64(data[2], ' ', &title3_data);
// load l1 data
std::vector<int64_t> l1_data;
split_to_int64(data[3], ' ', &l1_data);
title1.push_back(std::move(title1_data));
title2.push_back(std::move(title2_data));
title3.push_back(std::move(title3_data));
l1.push_back(std::move(l1_data));
}
num_samples = num_lines;
}
};
void PrepareInputs(std::vector<PaddleTensor> *input_slots,
DataRecord *data,
int batch_size) {
PaddleTensor title1_tensor, title2_tensor, title3_tensor, l1_tensor;
title1_tensor.name = "title1";
title2_tensor.name = "title2";
title3_tensor.name = "title3";
l1_tensor.name = "l1";
auto one_batch = data->NextBatch();
// assign data
TensorAssignData<int64_t>(&title1_tensor, one_batch.title1, one_batch.lod1);
TensorAssignData<int64_t>(&title2_tensor, one_batch.title2, one_batch.lod2);
TensorAssignData<int64_t>(&title3_tensor, one_batch.title3, one_batch.lod3);
TensorAssignData<int64_t>(&l1_tensor, one_batch.l1, one_batch.l1_lod);
// Set inputs.
input_slots->assign({title1_tensor, title2_tensor, title3_tensor, l1_tensor});
for (auto &tensor : *input_slots) {
tensor.dtype = PaddleDType::INT64;
}
}
void SetConfig(AnalysisConfig *cfg) {
cfg->SetModel(FLAGS_infer_model);
cfg->DisableGpu();
cfg->SwitchSpecifyInputNames();
cfg->SwitchIrOptim();
}
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
DataRecord data(FLAGS_infer_data, FLAGS_batch_size);
std::vector<PaddleTensor> input_slots;
int epoch =
FLAGS_test_all_data ? data.num_samples / FLAGS_batch_size : 1; // NOLINT
LOG(INFO) << "number of samples: " << epoch * FLAGS_batch_size;
for (int bid = 0; bid < epoch; ++bid) {
PrepareInputs(&input_slots, &data, FLAGS_batch_size);
(*inputs).emplace_back(input_slots);
}
}
// Easy for profiling independently.
TEST(Analyzer_seq_conv1, profile) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all,
&outputs,
FLAGS_num_threads);
if (FLAGS_num_threads == 1 && !FLAGS_test_all_data) {
// the first inference result
PADDLE_ENFORCE_GT(
outputs.size(),
0,
common::errors::Fatal("The size of output should be greater than 0."));
auto output = outputs.back();
PADDLE_ENFORCE_EQ(
output.size(),
1UL,
common::errors::Fatal("The size of output should be equal to 0."));
size_t size = GetSize(output[0]);
PADDLE_ENFORCE_GT(
size,
0,
common::errors::Fatal("The size of output should be greater than 0."));
float *result = static_cast<float *>(output[0].data.data());
// output is probability, which is in (0, 1).
for (size_t i = 0; i < size; i++) {
EXPECT_GT(result[i], 0);
EXPECT_LT(result[i], 1);
}
}
}
// Compare result of NativeConfig and AnalysisConfig
TEST(Analyzer_seq_conv1, compare) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareNativeAndAnalysis(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg), input_slots_all);
}
// Compare Deterministic result
TEST(Analyzer_seq_conv1, compare_determine) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareDeterministic(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all);
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,41 @@
/* 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 <algorithm>
#include <fstream>
#include <iostream>
#include "test/cpp/inference/api/analyzer_seq_pool1_tester_helper.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
namespace seq_pool1_tester {
// Compare Deterministic result
TEST(Analyzer_seq_pool1_compare_determine, compare_determine) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareDeterministic(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all);
}
} // namespace seq_pool1_tester
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,40 @@
/* 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 <algorithm>
#include <fstream>
#include <iostream>
#include "test/cpp/inference/api/analyzer_seq_pool1_tester_helper.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
namespace seq_pool1_tester {
TEST(Analyzer_seq_pool1_compare, compare) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareNativeAndAnalysis(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg), input_slots_all);
}
} // namespace seq_pool1_tester
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,48 @@
/* 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 <algorithm>
#include <fstream>
#include <iostream>
#include "test/cpp/inference/api/analyzer_seq_pool1_tester_helper.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
namespace seq_pool1_tester {
// Compare result of AnalysisConfig and AnalysisConfig + ZeroCopy
TEST(Analyzer_seq_pool1_compare_zero_copy, compare_zero_copy) {
AnalysisConfig cfg;
SetConfig(&cfg);
AnalysisConfig cfg1;
SetConfig(&cfg1);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
std::vector<std::string> outputs_name;
outputs_name.emplace_back(out_var_name);
CompareAnalysisAndZeroCopy(reinterpret_cast<PaddlePredictor::Config *>(&cfg),
reinterpret_cast<PaddlePredictor::Config *>(&cfg1),
input_slots_all,
outputs_name);
}
} // namespace seq_pool1_tester
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,45 @@
/* 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 <algorithm>
#include <fstream>
#include <iostream>
#include "test/cpp/inference/api/analyzer_seq_pool1_tester_helper.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
namespace seq_pool1_tester {
void profile(bool use_onednn = false) {
AnalysisConfig cfg;
SetConfig(&cfg, use_onednn);
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all,
&outputs,
FLAGS_num_threads);
}
TEST(Analyzer_seq_pool1_profile, profile) { profile(); }
} // namespace seq_pool1_tester
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,178 @@
/* 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. */
#pragma once
#include <algorithm>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
namespace seq_pool1_tester {
// diff: similarity_norm.tmp_0, for speed: fc_4.tmp_1
static const char out_var_name[] = "reduce_sum_0.tmp_0";
// for diff: 154, for speed 111
constexpr int num_slots = 154;
struct OneSlotInBatch {
std::string name;
std::vector<std::vector<float>> data;
std::vector<int> shape;
std::vector<size_t> lod;
};
struct DataRecord {
std::vector<std::vector<OneSlotInBatch>> batched_data;
std::map<std::string, std::vector<std::vector<float>>> datasets;
size_t batch_iter{0}, num_samples; // total number of samples
DataRecord() = default;
explicit DataRecord(const std::string &path, int batch_size = 1) {
Load(path);
Prepare(batch_size);
}
void Load(const std::string &path) {
std::ifstream file(path);
std::string line;
int num_lines = 0;
while (std::getline(file, line)) {
num_lines++;
std::vector<std::string> data;
split(line, '\t', &data);
std::vector<float> slot_data;
split_to_float(data[1], ' ', &slot_data);
std::string name = data[0];
PADDLE_ENFORCE_EQ(
slot_data.size() % 11,
0UL,
::common::errors::Fatal(
"line %d, %s should be divisible", num_lines, name));
datasets[name].emplace_back(std::move(slot_data));
}
num_samples = num_lines / num_slots;
PADDLE_ENFORCE_EQ(
num_samples * num_slots,
static_cast<size_t>(num_lines),
::common::errors::Fatal("num samples should be divisible"));
PADDLE_ENFORCE_GT(num_samples,
0UL,
::common::errors::Fatal(
"The num of samples should be greater than 0."));
}
void Prepare(int bs) {
for (auto it = datasets.begin(); it != datasets.end(); ++it) {
PADDLE_ENFORCE_EQ(
it->second.size(),
num_samples,
::common::errors::Fatal("size of each slot should be equal"));
}
size_t num_batches = num_samples / bs;
EXPECT_GT(num_batches, 0UL);
batched_data.resize(num_batches);
for (auto &one_batch : batched_data) {
one_batch.resize(datasets.size());
size_t i = 0;
for (auto it = datasets.begin(); it != datasets.end(); ++it) {
auto &slot = one_batch[i];
slot.name = it->first;
slot.data.resize(bs);
slot.lod.resize(bs + 1);
slot.lod[0] = 0;
auto &lod = slot.lod;
auto &datas = it->second;
for (int k = 0; k < bs; ++k) {
size_t id = k + batch_iter * bs;
std::copy(datas[id].begin(),
datas[id].end(),
std::back_inserter(slot.data[k]));
size_t len = datas[id].size() / 11;
PADDLE_ENFORCE_EQ(
len * 11,
datas[id].size(),
::common::errors::Fatal(
"%s %d size should be divisible", slot.name, id));
lod[k + 1] = lod[k] + len;
}
slot.shape.assign({static_cast<int>(lod[bs]), 11});
i++;
}
}
}
const std::vector<OneSlotInBatch> &NextBatch() {
if (batch_iter >= batched_data.size() - 1) {
batch_iter = -1;
}
return batched_data[++batch_iter];
}
};
static void TensorAssignSlot(PaddleTensor *tensor, const OneSlotInBatch &slot) {
tensor->name = slot.name + "_embed";
tensor->shape = slot.shape;
tensor->dtype = PaddleDType::FLOAT32;
tensor->lod.clear();
tensor->lod.emplace_back(slot.lod);
TensorAssignData(tensor, slot.data);
}
void PrepareInputs(std::vector<PaddleTensor> *input_slots, DataRecord *data) {
const auto &one_batch = data->NextBatch();
input_slots->resize(one_batch.size());
for (size_t i = 0; i < one_batch.size(); ++i) {
auto &slot = one_batch[i];
TensorAssignSlot(&((*input_slots)[i]), slot);
}
}
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
DataRecord data(FLAGS_infer_data, FLAGS_batch_size);
std::vector<PaddleTensor> input_slots;
int epoch = FLAGS_test_all_data ? data.batched_data.size() : 1;
LOG(INFO) << "number of samples: "
<< data.batched_data.size() * FLAGS_batch_size;
for (int bid = 0; bid < epoch; ++bid) {
PrepareInputs(&input_slots, &data);
(*inputs).emplace_back(input_slots);
}
}
void SetConfig(AnalysisConfig *cfg, bool use_onednn = false) {
cfg->SetModel(FLAGS_infer_model + "/model", FLAGS_infer_model + "/params");
cfg->DisableGpu();
cfg->SwitchSpecifyInputNames();
cfg->SwitchIrDebug();
cfg->SetCpuMathLibraryNumThreads(FLAGS_cpu_num_threads);
if (use_onednn) {
cfg->EnableONEDNN();
}
// Enable seqpool_concat_fuse_pass, disabled by default since it takes much
// time
cfg->pass_builder()->InsertPass(2, "seqpool_concat_fuse_pass");
}
} // namespace seq_pool1_tester
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,161 @@
// 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 "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
struct DataReader {
explicit DataReader(const std::string &path)
: file(new std::ifstream(path)) {}
bool NextBatch(std::vector<PaddleTensor> *input, int batch_size) {
PADDLE_ENFORCE_EQ(
batch_size,
1,
common::errors::Fatal("The size of batch should be equal to 1."));
std::string line;
PaddleTensor tensor;
tensor.dtype = PaddleDType::INT64;
tensor.lod.emplace_back(std::vector<size_t>({0}));
std::vector<int64_t> data;
for (int i = 0; i < batch_size; i++) {
if (!std::getline(*file, line)) return false;
inference::split_to_int64(line, ' ', &data);
}
tensor.lod.front().push_back(data.size());
tensor.data.Resize(data.size() * sizeof(int64_t));
PADDLE_ENFORCE_NE(
tensor.data.data(),
nullptr,
common::errors::Fatal("Variable `tensor.data.data()` is nullptr"));
PADDLE_ENFORCE_NE(
data.data(),
nullptr,
common::errors::Fatal("Variable `data.data()` is nullptr"));
memcpy(tensor.data.data(), data.data(), data.size() * sizeof(int64_t));
tensor.shape.push_back(data.size());
tensor.shape.push_back(1);
input->assign({tensor});
return true;
}
std::unique_ptr<std::ifstream> file = nullptr;
};
void SetConfig(AnalysisConfig *cfg) {
cfg->SetModel(FLAGS_infer_model);
cfg->DisableGpu();
cfg->SwitchSpecifyInputNames();
cfg->SwitchIrOptim();
}
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
std::vector<PaddleTensor> input_slots;
DataReader reader(FLAGS_infer_data);
int num_batches = 0;
while (reader.NextBatch(&input_slots, FLAGS_batch_size)) {
(*inputs).emplace_back(input_slots);
++num_batches;
if (!FLAGS_test_all_data) return;
}
LOG(INFO) << "total number of samples: " << num_batches * FLAGS_batch_size;
}
// Easy for profiling independently.
TEST(Analyzer_Text_Classification, profile) {
AnalysisConfig cfg;
SetConfig(&cfg);
cfg.SwitchIrDebug();
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all,
&outputs,
FLAGS_num_threads);
if (FLAGS_num_threads == 1) {
// Get output
PADDLE_ENFORCE_GT(
outputs.size(),
0,
common::errors::Fatal("The size of output should be greater than 0."));
LOG(INFO) << "get outputs " << outputs.back().size();
for (auto &output : outputs.back()) {
LOG(INFO) << "output.shape: " << to_string(output.shape);
// no lod ?
PADDLE_ENFORCE_EQ(
output.lod.size(),
0UL,
common::errors::InvalidArgument(
"The 'lod' size of 'output' should be 0, but received size %d.",
output.lod.size()));
LOG(INFO) << "output.dtype: " << output.dtype;
std::stringstream ss;
int num_data = 1;
for (auto i : output.shape) {
num_data *= i;
}
for (int i = 0; i < num_data; i++) {
ss << static_cast<float *>(output.data.data())[i] << " ";
}
LOG(INFO) << "output.data summary: " << ss.str();
// one batch ends
}
}
}
// Compare result of NativeConfig and AnalysisConfig
TEST(Analyzer_Text_Classification, compare) {
AnalysisConfig cfg;
SetConfig(&cfg);
cfg.EnableMemoryOptim();
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareNativeAndAnalysis(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg), input_slots_all);
}
// Compare Deterministic result
TEST(Analyzer_Text_Classification, compare_determine) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareDeterministic(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all);
}
TEST(Analyzer_Text_Classification, compare_against_embedding_fc_lstm_fused) {
AnalysisConfig cfg;
SetConfig(&cfg);
// Enable embedding_fc_lstm_fuse_pass (disabled by default)
cfg.pass_builder()->InsertPass(2, "embedding_fc_lstm_fuse_pass");
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareNativeAndAnalysis(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg), input_slots_all);
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,203 @@
// 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.
#pragma once
#include <string>
#include <utility>
#include <vector>
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
namespace transformer_tester {
struct DataRecord {
std::vector<std::vector<int64_t>> src_word, src_pos, trg_word, init_idx;
std::vector<std::vector<float>> src_slf_attn_bias, init_score,
trg_src_attn_bias;
std::vector<std::vector<int32_t>> batch_data_shape;
std::vector<std::vector<size_t>> lod;
size_t batch_iter{0}, batch_size{1}, num_samples; // total number of samples
DataRecord() = default;
explicit DataRecord(const std::string &path, int batch_size = 1)
: batch_size(batch_size) {
Load(path);
}
DataRecord NextBatch() {
DataRecord data;
size_t batch_end = batch_iter + batch_size;
// NOTE skip the final batch, if no enough data is provided.
if (batch_end <= src_word.size()) {
data.src_word.assign(src_word.begin() + batch_iter,
src_word.begin() + batch_end);
data.src_pos.assign(src_pos.begin() + batch_iter,
src_pos.begin() + batch_end);
data.src_slf_attn_bias.assign(src_slf_attn_bias.begin() + batch_iter,
src_slf_attn_bias.begin() + batch_end);
data.trg_word.assign(trg_word.begin() + batch_iter,
trg_word.begin() + batch_end);
data.init_score.assign(init_score.begin() + batch_iter,
init_score.begin() + batch_end);
data.init_idx.assign(init_idx.begin() + batch_iter,
init_idx.begin() + batch_end);
data.trg_src_attn_bias.assign(trg_src_attn_bias.begin() + batch_iter,
trg_src_attn_bias.begin() + batch_end);
std::vector<int32_t> batch_shape =
*(batch_data_shape.begin() + batch_iter);
data.batch_data_shape.push_back(batch_shape);
data.lod.resize(2);
for (int i = 0; i < batch_shape[0] + 1; i++) {
data.lod[0].push_back(i);
data.lod[1].push_back(i);
}
}
batch_iter += batch_size;
return data;
}
void Load(const std::string &path) {
std::ifstream file(path);
std::string line;
size_t num_lines = 0;
while (std::getline(file, line)) {
num_lines++;
std::vector<std::string> data;
split(line, ',', &data);
PADDLE_ENFORCE_EQ(data.size(),
static_cast<size_t>(8),
common::errors::InvalidArgument(
"The size of data should be equal to 8. "));
// load src_word
std::vector<int64_t> src_word_data;
split_to_int64(data[0], ' ', &src_word_data);
src_word.push_back(std::move(src_word_data));
// load src_pos
std::vector<int64_t> src_pos_data;
split_to_int64(data[1], ' ', &src_pos_data);
src_pos.push_back(std::move(src_pos_data));
// load src_slf_attn_bias
std::vector<float> src_slf_attn_bias_data;
split_to_float(data[2], ' ', &src_slf_attn_bias_data);
src_slf_attn_bias.push_back(std::move(src_slf_attn_bias_data));
// load trg_word
std::vector<int64_t> trg_word_data;
split_to_int64(data[3], ' ', &trg_word_data);
trg_word.push_back(std::move(trg_word_data));
// load init_score
std::vector<float> init_score_data;
split_to_float(data[4], ' ', &init_score_data);
init_score.push_back(std::move(init_score_data));
// load init_idx
std::vector<int64_t> init_idx_data;
split_to_int64(data[5], ' ', &init_idx_data);
init_idx.push_back(std::move(init_idx_data));
// load trg_src_attn_bias
std::vector<float> trg_src_attn_bias_data;
split_to_float(data[6], ' ', &trg_src_attn_bias_data);
trg_src_attn_bias.push_back(std::move(trg_src_attn_bias_data));
// load shape for variant data shape
std::vector<int> batch_data_shape_data;
split_to_int(data[7], ' ', &batch_data_shape_data);
batch_data_shape.push_back(std::move(batch_data_shape_data));
}
num_samples = num_lines;
}
};
void PrepareInputs(std::vector<PaddleTensor> *input_slots,
DataRecord *data,
int batch_size) {
auto one_batch = data->NextBatch();
batch_size = one_batch.batch_data_shape[0][0];
auto n_head = one_batch.batch_data_shape[0][1];
auto trg_seq_len = one_batch.batch_data_shape[0][2]; // 1 for inference
auto src_seq_len = one_batch.batch_data_shape[0][3];
PaddleTensor src_word, src_pos, src_slf_attn_bias, trg_word, init_score,
init_idx, trg_src_attn_bias;
src_word.name = "src_word";
src_word.shape.assign({batch_size, src_seq_len, 1});
src_word.dtype = PaddleDType::INT64;
TensorAssignData<int64_t>(&src_word, one_batch.src_word);
src_pos.name = "src_pos";
src_pos.shape.assign({batch_size, src_seq_len, 1});
src_pos.dtype = PaddleDType::INT64;
TensorAssignData<int64_t>(&src_pos, one_batch.src_pos);
src_slf_attn_bias.name = "src_slf_attn_bias";
src_slf_attn_bias.shape.assign(
{batch_size, n_head, src_seq_len, src_seq_len});
src_slf_attn_bias.dtype = PaddleDType::FLOAT32;
TensorAssignData<float>(&src_slf_attn_bias, one_batch.src_slf_attn_bias);
trg_word.name = "trg_word";
trg_word.shape.assign({batch_size, 1});
trg_word.dtype = PaddleDType::INT64;
trg_word.lod.assign(one_batch.lod.begin(), one_batch.lod.end());
TensorAssignData<int64_t>(&trg_word, one_batch.trg_word);
init_score.name = "init_score";
init_score.shape.assign({batch_size, 1});
init_score.dtype = PaddleDType::FLOAT32;
init_score.lod.assign(one_batch.lod.begin(), one_batch.lod.end());
TensorAssignData<float>(&init_score, one_batch.init_score);
init_idx.name = "init_idx";
init_idx.shape.assign({batch_size});
init_idx.dtype = PaddleDType::INT64;
TensorAssignData<int64_t>(&init_idx, one_batch.init_idx);
trg_src_attn_bias.name = "trg_src_attn_bias";
trg_src_attn_bias.shape.assign(
{batch_size, n_head, trg_seq_len, src_seq_len});
trg_src_attn_bias.dtype = PaddleDType::FLOAT32;
TensorAssignData<float>(&trg_src_attn_bias, one_batch.trg_src_attn_bias);
input_slots->assign({src_word,
src_pos,
src_slf_attn_bias,
trg_word,
init_score,
init_idx,
trg_src_attn_bias});
}
void SetConfig(AnalysisConfig *cfg) {
cfg->SetModel(FLAGS_infer_model + "/model", FLAGS_infer_model + "/params");
cfg->DisableGpu();
cfg->SwitchSpecifyInputNames();
cfg->SwitchIrOptim();
cfg->SetCpuMathLibraryNumThreads(FLAGS_cpu_num_threads);
}
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
DataRecord data(FLAGS_infer_data, FLAGS_batch_size);
std::vector<PaddleTensor> input_slots;
int test_batch_num =
FLAGS_test_all_data ? data.num_samples / FLAGS_batch_size : 1;
LOG(INFO) << "The number of samples to be test: "
<< test_batch_num * FLAGS_batch_size;
for (int bid = 0; bid < test_batch_num; ++bid) {
input_slots.clear();
PrepareInputs(&input_slots, &data, FLAGS_batch_size);
(*inputs).emplace_back(input_slots);
}
}
} // namespace transformer_tester
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,168 @@
/* 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 <gtest/gtest.h>
#include <fstream>
#include <iostream>
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
struct Record {
std::vector<float> data;
std::vector<int32_t> shape;
Record() : data(), shape() {}
};
Record ProcessALine(const std::string &line) {
VLOG(3) << "process a line";
std::vector<std::string> columns;
split(line, '\t', &columns);
PADDLE_ENFORCE_EQ(columns.size(),
2UL,
common::errors::InvalidArgument(
"data format error, should be <data>\t<shape>"));
Record record;
std::vector<std::string> data_strs;
split(columns[0], ' ', &data_strs);
for (auto &d : data_strs) {
record.data.push_back(std::stof(d));
}
std::vector<std::string> shape_strs;
split(columns[1], ' ', &shape_strs);
for (auto &s : shape_strs) {
record.shape.push_back(std::stoi(s));
}
VLOG(3) << "data size " << record.data.size();
VLOG(3) << "data shape size " << record.shape.size();
return record;
}
void SetConfig(AnalysisConfig *cfg) {
cfg->SetModel(FLAGS_infer_model + "/__model__",
FLAGS_infer_model + "/__params__");
cfg->DisableGpu();
cfg->SwitchIrDebug();
cfg->SwitchSpecifyInputNames(false);
}
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
PADDLE_ENFORCE_EQ(FLAGS_test_all_data,
0,
::common::errors::Fatal("Only have single batch of data."));
std::string line;
std::ifstream file(FLAGS_infer_data);
std::getline(file, line);
auto record = ProcessALine(line);
PaddleTensor input;
input.shape = record.shape;
input.dtype = PaddleDType::FLOAT32;
size_t input_size = record.data.size() * sizeof(float);
input.data.Resize(input_size);
memcpy(input.data.data(), record.data.data(), input_size);
std::vector<PaddleTensor> input_slots;
input_slots.assign({input});
(*inputs).emplace_back(input_slots);
}
// Easy for profiling independently.
// ocr, mobilenet and se_resnext50
void profile(bool use_onednn = false) {
AnalysisConfig cfg;
SetConfig(&cfg);
if (use_onednn) {
cfg.EnableONEDNN();
}
// cfg.pass_builder()->TurnOnDebug();
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all,
&outputs,
FLAGS_num_threads);
if (FLAGS_num_threads == 1 && !FLAGS_test_all_data) {
std::string line;
std::ifstream file(FLAGS_refer_result);
std::getline(file, line);
auto refer = ProcessALine(line);
file.close();
PADDLE_ENFORCE_GT(outputs.size(),
0,
::common::errors::Fatal(
"The size of output should be greater than 0."));
auto &output = outputs.back().front();
size_t numel = output.data.length() / PaddleDtypeSize(output.dtype);
PADDLE_ENFORCE_EQ(
numel,
refer.data.size(),
common::errors::InvalidArgument(
"value of numel is wrong, expected %d but received %d",
refer.data.size(),
numel));
for (size_t i = 0; i < numel; ++i) {
EXPECT_NEAR(
static_cast<float *>(output.data.data())[i], refer.data[i], 1e-5);
}
}
}
TEST(Analyzer_vis, profile) { profile(); }
#ifdef PADDLE_WITH_DNNL
TEST(Analyzer_vis, profile_onednn) { profile(true /* use_onednn */); }
#endif
// Compare result of NativeConfig and AnalysisConfig
void compare(bool use_onednn = false) {
AnalysisConfig cfg;
SetConfig(&cfg);
if (use_onednn) {
cfg.EnableONEDNN();
}
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareNativeAndAnalysis(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg), input_slots_all);
}
TEST(Analyzer_vis, compare) { compare(); }
#ifdef PADDLE_WITH_DNNL
TEST(Analyzer_vis, compare_onednn) { compare(true /* use_onednn */); }
#endif
// Compare Deterministic result
TEST(Analyzer_vis, compare_determine) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareDeterministic(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all);
}
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,100 @@
/* Copyright (c) 2022 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 <fstream>
#include <iostream>
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
namespace analysis {
struct Record {
std::vector<float> data;
std::vector<int32_t> shape;
Record() : data(), shape() {}
};
Record ProcessALine(const std::string &line) {
std::vector<std::string> columns;
split(line, '\t', &columns);
PADDLE_ENFORCE_EQ(columns.size(),
2UL,
common::errors::InvalidArgument(
"Data format is invalid, should be <data>\t<shape>"));
Record record;
std::vector<std::string> data_strs;
split(columns[0], ' ', &data_strs);
for (auto &d : data_strs) {
record.data.push_back(std::stof(d));
}
std::vector<std::string> shape_strs;
split(columns[1], ' ', &shape_strs);
for (auto &s : shape_strs) {
record.shape.push_back(std::stoi(s));
}
return record;
}
void SetInput(std::vector<std::vector<PaddleTensor>> *inputs) {
std::string line;
std::ifstream file(FLAGS_infer_data);
std::getline(file, line);
auto record = ProcessALine(line);
PaddleTensor input;
input.shape = record.shape;
input.dtype = PaddleDType::FLOAT32;
size_t input_size = record.data.size() * sizeof(float);
input.data.Resize(input_size);
memcpy(input.data.data(), record.data.data(), input_size);
std::vector<PaddleTensor> input_slots;
input_slots.assign({input});
(*inputs).emplace_back(input_slots);
}
void SetConfig(AnalysisConfig *cfg, bool use_onednn = false) {
cfg->SetModel(FLAGS_infer_model + "/inference.pdmodel",
FLAGS_infer_model + "/inference.pdiparams");
if (use_onednn) {
cfg->EnableONEDNN();
cfg->SwitchIrOptim();
}
}
// Compare results of NativeConfig and AnalysisConfig
void compare(bool use_onednn = false) {
AnalysisConfig cfg;
SetConfig(&cfg, use_onednn);
std::vector<std::vector<PaddleTensor>> input_slots_all;
SetInput(&input_slots_all);
CompareNativeAndAnalysis(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg), input_slots_all);
}
TEST(Analyzer_vit_ocr, compare) { compare(); }
#ifdef PADDLE_WITH_DNNL
TEST(Analyzer_vit_ocr, compare_onednn) { compare(true /* use_onednn */); }
#endif
} // namespace analysis
} // namespace inference
} // namespace paddle
@@ -0,0 +1,63 @@
// 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.
#include "paddle/fluid/framework/block_desc.h"
#include "paddle/fluid/framework/op_desc.h"
#include "paddle/fluid/framework/program_desc.h"
#include "paddle/fluid/framework/scope.h"
#include "paddle/fluid/inference/utils/singleton.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
TEST(test_zerocopy_tensor, zerocopy_tensor) {
AnalysisConfig config;
config.SetModel(FLAGS_infer_model + "/inference.pdmodel",
FLAGS_infer_model + "/inference.pdiparams");
auto predictor = CreatePaddlePredictor(config);
int batch_size = 1;
int channels = 3;
int height = 224;
int width = 224;
int nums = batch_size * channels * height * width;
float* input = new float[nums];
for (int i = 0; i < nums; ++i) input[i] = 0;
auto input_names = predictor->GetInputNames();
PaddlePlace p = PaddlePlace::kCPU;
PaddlePlace* place = &p;
int size;
auto input_t = predictor->GetInputTensor(input_names[0]);
input_t->Reshape({batch_size, channels, height, width});
input_t->copy_from_cpu<float>(input);
input_t->data<float>(place, &size);
input_t->mutable_data<float>(p);
predictor->ZeroCopyRun();
std::vector<float> out_data;
auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputTensor(output_names[0]);
std::vector<int> output_shape = output_t->shape();
int out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
out_data.resize(out_num);
output_t->copy_to_cpu<float>(out_data.data());
}
} // namespace inference
} // namespace paddle
+343
View File
@@ -0,0 +1,343 @@
/* 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <thread> // NOLINT
#include "paddle/common/flags.h"
#include "paddle/fluid/framework/convert_utils.h"
#include "paddle/fluid/inference/api/api_impl.h"
#include "test/cpp/inference/test_helper.h"
#ifdef __clang__
#define ACC_DIFF 4e-3
#else
#define ACC_DIFF 2e-3
#endif
PD_DEFINE_string(word2vec_dirname,
"",
"Directory of the word2vec inference model.");
PD_DEFINE_string(book_dirname, "", "Directory of the book inference model.");
namespace paddle {
PaddleTensor LodTensorToPaddleTensor(phi::DenseTensor* t) {
PaddleTensor pt;
if (framework::TransToProtoVarType(t->dtype()) ==
framework::proto::VarType::INT64) {
pt.data.Reset(t->data(), t->numel() * sizeof(int64_t));
pt.dtype = PaddleDType::INT64;
} else if (framework::TransToProtoVarType(t->dtype()) ==
framework::proto::VarType::FP32) {
pt.data.Reset(t->data(), t->numel() * sizeof(float));
pt.dtype = PaddleDType::FLOAT32;
} else if (framework::TransToProtoVarType(t->dtype()) ==
framework::proto::VarType::INT32) {
pt.data.Reset(t->data(), t->numel() * sizeof(int32_t));
pt.dtype = PaddleDType::INT32;
} else {
PADDLE_THROW(common::errors::Unimplemented(
"Unsupported tensor date type. Now only supports INT64, FP32, INT32."));
}
pt.shape = common::vectorize<int>(t->dims());
return pt;
}
NativeConfig GetConfig() {
NativeConfig config;
config.model_dir = FLAGS_word2vec_dirname;
LOG(INFO) << "dirname " << config.model_dir;
config.fraction_of_gpu_memory = 0.15;
config.device = 0;
return config;
}
void MainWord2Vec(const ::paddle::PaddlePlace& place) {
NativeConfig config = GetConfig();
auto predictor = CreatePaddlePredictor<NativeConfig>(config);
config.use_gpu = ::paddle::gpu_place_used(place);
config.use_xpu = ::paddle::xpu_place_used(place);
phi::DenseTensor first_word, second_word, third_word, fourth_word;
phi::LegacyLoD lod{{0, 1}};
int64_t dict_size = 2073; // The size of dictionary
SetupDenseTensor(&first_word, lod, static_cast<int64_t>(0), dict_size - 1);
SetupDenseTensor(&second_word, lod, static_cast<int64_t>(0), dict_size - 1);
SetupDenseTensor(&third_word, lod, static_cast<int64_t>(0), dict_size - 1);
SetupDenseTensor(&fourth_word, lod, static_cast<int64_t>(0), dict_size - 1);
std::vector<PaddleTensor> paddle_tensor_feeds;
paddle_tensor_feeds.push_back(LodTensorToPaddleTensor(&first_word));
paddle_tensor_feeds.push_back(LodTensorToPaddleTensor(&second_word));
paddle_tensor_feeds.push_back(LodTensorToPaddleTensor(&third_word));
paddle_tensor_feeds.push_back(LodTensorToPaddleTensor(&fourth_word));
std::vector<PaddleTensor> outputs;
ASSERT_TRUE(predictor->Run(paddle_tensor_feeds, &outputs));
ASSERT_EQ(outputs.size(), 1UL);
size_t len = outputs[0].data.length();
float* data = static_cast<float*>(outputs[0].data.data());
for (size_t j = 0; j < len / sizeof(float); ++j) {
ASSERT_LT(data[j], 1.0);
ASSERT_GT(data[j], -1.0);
}
std::vector<phi::DenseTensor*> cpu_feeds;
cpu_feeds.push_back(&first_word);
cpu_feeds.push_back(&second_word);
cpu_feeds.push_back(&third_word);
cpu_feeds.push_back(&fourth_word);
framework::FetchType output1;
std::vector<::paddle::framework::FetchType*> cpu_fetches1;
cpu_fetches1.push_back(&output1);
TestInference<phi::CPUPlace>(config.model_dir, cpu_feeds, cpu_fetches1);
auto output1_tensor = PADDLE_GET(phi::DenseTensor, output1);
float* lod_data = output1_tensor.data<float>();
for (int i = 0; i < output1_tensor.numel(); ++i) {
EXPECT_LT(lod_data[i] - data[i], ACC_DIFF);
EXPECT_GT(lod_data[i] - data[i], -ACC_DIFF);
}
}
void MainImageClassification(const ::paddle::PaddlePlace& place) {
int batch_size = 2;
bool repeat = false;
NativeConfig config = GetConfig();
config.use_gpu = ::paddle::gpu_place_used(place);
config.use_xpu = ::paddle::xpu_place_used(place);
config.model_dir =
FLAGS_book_dirname + "/image_classification_resnet.inference.model";
const bool is_combined = false;
std::vector<std::vector<int64_t>> feed_target_shapes =
GetFeedTargetShapes(config.model_dir, is_combined);
phi::DenseTensor input;
// Use normilized image pixels as input data,
// which should be in the range [0.0, 1.0].
feed_target_shapes[0][0] = batch_size;
phi::DDim input_dims = common::make_ddim(feed_target_shapes[0]);
SetupTensor<float>(
&input, input_dims, static_cast<float>(0), static_cast<float>(1));
std::vector<phi::DenseTensor*> cpu_feeds;
cpu_feeds.push_back(&input);
framework::FetchType output1;
std::vector<framework::FetchType*> cpu_fetches1;
cpu_fetches1.push_back(&output1);
TestInference<phi::CPUPlace, false, true>(
config.model_dir, cpu_feeds, cpu_fetches1, repeat, is_combined);
auto predictor = CreatePaddlePredictor(config);
std::vector<PaddleTensor> paddle_tensor_feeds;
paddle_tensor_feeds.push_back(LodTensorToPaddleTensor(&input));
std::vector<PaddleTensor> outputs;
ASSERT_TRUE(predictor->Run(paddle_tensor_feeds, &outputs));
ASSERT_EQ(outputs.size(), 1UL);
size_t len = outputs[0].data.length();
float* data = static_cast<float*>(outputs[0].data.data());
float* lod_data = PADDLE_GET(phi::DenseTensor, output1).data<float>();
for (size_t j = 0; j < len / sizeof(float); ++j) {
EXPECT_NEAR(lod_data[j], data[j], ACC_DIFF);
}
}
void MainThreadsWord2Vec(const ::paddle::PaddlePlace& place) {
NativeConfig config = GetConfig();
config.use_gpu = ::paddle::gpu_place_used(place);
config.use_xpu = ::paddle::xpu_place_used(place);
auto main_predictor = CreatePaddlePredictor<NativeConfig>(config);
// prepare inputs data and reference results
constexpr int num_jobs = 3;
std::vector<std::vector<phi::DenseTensor>> jobs(num_jobs);
std::vector<std::vector<PaddleTensor>> paddle_tensor_feeds(num_jobs);
std::vector<framework::FetchType> refs(num_jobs);
for (size_t i = 0; i < jobs.size(); ++i) {
// each job has 4 words
jobs[i].resize(4);
for (size_t j = 0; j < 4; ++j) {
phi::LegacyLoD lod{{0, 1}};
int64_t dict_size = 2073; // The size of dictionary
SetupDenseTensor(
&jobs[i][j], lod, static_cast<int64_t>(0), dict_size - 1);
paddle_tensor_feeds[i].push_back(LodTensorToPaddleTensor(&jobs[i][j]));
}
// get reference result of each job
std::vector<phi::DenseTensor*> ref_feeds;
std::vector<::paddle::framework::FetchType*> ref_fetches(1, &refs[i]);
for (auto& word : jobs[i]) {
ref_feeds.push_back(&word);
}
TestInference<phi::CPUPlace>(config.model_dir, ref_feeds, ref_fetches);
}
// create threads and each thread run 1 job
std::vector<std::thread> threads;
for (int tid = 0; tid < num_jobs; ++tid) {
threads.emplace_back([&, tid]() {
auto predictor = CreatePaddlePredictor(config);
auto& local_inputs = paddle_tensor_feeds[tid];
std::vector<PaddleTensor> local_outputs;
ASSERT_TRUE(predictor->Run(local_inputs, &local_outputs));
// check outputs range
ASSERT_EQ(local_outputs.size(), 1UL);
const size_t len = local_outputs[0].data.length();
float* data = static_cast<float*>(local_outputs[0].data.data());
for (size_t j = 0; j < len / sizeof(float); ++j) {
ASSERT_LT(data[j], 1.0);
ASSERT_GT(data[j], -1.0);
}
// check outputs correctness
auto ref_tensor = PADDLE_GET(phi::DenseTensor, refs[tid]);
float* ref_data = ref_tensor.data<float>();
EXPECT_EQ(ref_tensor.numel(), static_cast<int64_t>(len / sizeof(float)));
for (int i = 0; i < ref_tensor.numel(); ++i) {
EXPECT_NEAR(ref_data[i], data[i], 2e-3);
}
});
}
for (int i = 0; i < num_jobs; ++i) {
threads[i].join();
}
}
void MainThreadsImageClassification(const ::paddle::PaddlePlace& place) {
constexpr int num_jobs = 4; // each job run 1 batch
constexpr int batch_size = 1;
NativeConfig config = GetConfig();
config.use_gpu = ::paddle::gpu_place_used(place);
config.use_xpu = ::paddle::xpu_place_used(place);
config.model_dir =
FLAGS_book_dirname + "/image_classification_resnet.inference.model";
auto main_predictor = CreatePaddlePredictor<NativeConfig>(config);
std::vector<phi::DenseTensor> jobs(num_jobs);
std::vector<std::vector<PaddleTensor>> paddle_tensor_feeds(num_jobs);
std::vector<framework::FetchType> refs(num_jobs);
for (size_t i = 0; i < jobs.size(); ++i) {
// prepare inputs
std::vector<std::vector<int64_t>> feed_target_shapes =
GetFeedTargetShapes(config.model_dir, /*is_combined*/ false);
feed_target_shapes[0][0] = batch_size;
phi::DDim input_dims = common::make_ddim(feed_target_shapes[0]);
SetupTensor<float>(&jobs[i], input_dims, 0.f, 1.f);
paddle_tensor_feeds[i].push_back(LodTensorToPaddleTensor(&jobs[i]));
// get reference result of each job
std::vector<phi::DenseTensor*> ref_feeds(1, &jobs[i]);
std::vector<framework::FetchType*> ref_fetches(1, &refs[i]);
TestInference<phi::CPUPlace>(config.model_dir, ref_feeds, ref_fetches);
}
// create threads and each thread run 1 job
std::vector<std::thread> threads;
for (int tid = 0; tid < num_jobs; ++tid) {
threads.emplace_back([&, tid]() {
auto predictor = CreatePaddlePredictor(config);
auto& local_inputs = paddle_tensor_feeds[tid];
std::vector<PaddleTensor> local_outputs;
ASSERT_TRUE(predictor->Run(local_inputs, &local_outputs));
// check outputs correctness
ASSERT_EQ(local_outputs.size(), 1UL);
const size_t len = local_outputs[0].data.length();
float* data = static_cast<float*>(local_outputs[0].data.data());
auto ref_tensor = PADDLE_GET(phi::DenseTensor, refs[tid]);
float* ref_data = ref_tensor.data<float>();
EXPECT_EQ((size_t)ref_tensor.numel(), len / sizeof(float));
for (int i = 0; i < ref_tensor.numel(); ++i) {
EXPECT_NEAR(ref_data[i], data[i], ACC_DIFF);
}
});
}
for (int i = 0; i < num_jobs; ++i) {
threads[i].join();
}
}
TEST(inference_api_native, word2vec_cpu) {
MainWord2Vec(::paddle::PaddlePlace::kCPU);
}
TEST(inference_api_native, word2vec_cpu_threads) {
MainThreadsWord2Vec(::paddle::PaddlePlace::kCPU);
}
TEST(inference_api_native, image_classification_cpu) {
MainImageClassification(::paddle::PaddlePlace::kCPU);
}
TEST(inference_api_native, image_classification_cpu_threads) {
MainThreadsImageClassification(::paddle::PaddlePlace::kCPU);
}
#ifdef PADDLE_WITH_XPU
TEST(inference_api_native, word2vec_xpu) {
MainWord2Vec(::paddle::PaddlePlace::kXPU);
}
TEST(inference_api_native, image_classification_xpu) {
MainImageClassification(::paddle::PaddlePlace::kXPU);
}
#endif
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
TEST(inference_api_native, word2vec_gpu) {
MainWord2Vec(::paddle::PaddlePlace::kGPU);
}
// Turn off temporarily for the unstable result.
// TEST(inference_api_native, word2vec_gpu_threads) {
// MainThreadsWord2Vec(::paddle::PaddlePlace::kGPU);
// }
TEST(inference_api_native, image_classification_gpu) {
MainImageClassification(::paddle::PaddlePlace::kGPU);
}
// Turn off temporarily for the unstable result.
// TEST(inference_api_native, image_classification_gpu_threads) {
// MainThreadsImageClassification(::paddle::PaddlePlace::kGPU);
// }
#endif
#ifdef PADDLE_WITH_DNNL
TEST(inference_api_native, image_classification_cpu_onednn) {
FLAGS_use_onednn = true;
MainImageClassification(::paddle::PaddlePlace::kCPU);
}
TEST(inference_api_native, word2vec_cpu_onednn) {
FLAGS_use_onednn = true;
MainWord2Vec(::paddle::PaddlePlace::kCPU);
}
#endif
TEST(PassBuilder, Delete) {
AnalysisConfig config;
config.DisableGpu();
config.pass_builder()->DeletePass("attention_lstm_fuse_pass");
const auto& passes = config.pass_builder()->AllPasses();
auto it = std::find(passes.begin(), passes.end(), "attention_lstm_fuse_pass");
ASSERT_EQ(it, passes.end());
}
} // namespace paddle
+112
View File
@@ -0,0 +1,112 @@
/* 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <exception>
#include <string>
#include "paddle/fluid/inference/api/paddle_analysis_config.h"
#include "paddle/fluid/inference/api/paddle_api.h"
#include "paddle/fluid/platform/enforce.h"
namespace paddle {
/*
* Do not use this, just a demo indicating how to customize a config for a
* specific predictor.
*/
struct DemoConfig : public PaddlePredictor::Config {
float other_config;
DemoConfig() : other_config(0) {}
};
/*
* Do not use this, just a demo indicating how to customize a Predictor.
*/
class DemoPredictor : public PaddlePredictor {
public:
explicit DemoPredictor(const DemoConfig &config) {
LOG(INFO) << "I get other_config " << config.other_config;
}
bool Run(const std::vector<PaddleTensor> &inputs,
std::vector<PaddleTensor> *output_data,
int batch_size = 0) override {
LOG(INFO) << "Run";
return false;
}
std::unique_ptr<PaddlePredictor> Clone(void *stream = nullptr) override {
return nullptr;
}
~DemoPredictor() override = default;
};
template <>
std::unique_ptr<PaddlePredictor> CreatePaddlePredictor<DemoConfig>(
const DemoConfig &config) {
std::unique_ptr<PaddlePredictor> x(new DemoPredictor(config));
return x;
}
TEST(paddle_inference_api, demo) {
DemoConfig config;
config.other_config = 1.7;
auto predictor = CreatePaddlePredictor(config);
std::vector<PaddleTensor> outputs;
predictor->Run({}, &outputs);
predictor->TryShrinkMemory();
}
TEST(paddle_inference_api, get_version) {
LOG(INFO) << "paddle version:\n" << get_version();
auto version = get_version();
ASSERT_FALSE(version.empty());
}
TEST(paddle_inference_api, UpdateDllFlag) {
UpdateDllFlag("paddle_num_threads", "10");
try {
UpdateDllFlag("paddle_num_threads2", "10");
} catch (std::exception &e) {
LOG(INFO) << e.what();
}
}
TEST(paddle_inference_api, AnalysisConfigCopyCtor) {
AnalysisConfig cfg1;
cfg1.EnableUseGpu(10);
#ifdef PADDLE_WITH_TENSORRT
cfg1.EnableTensorRtEngine();
#endif
std::string delete_pass("skip_layernorm_fuse_pass");
cfg1.pass_builder()->DeletePass(delete_pass);
AnalysisConfig cfg2(cfg1);
auto passes = cfg2.pass_builder()->AllPasses();
for (auto const &ps : passes) {
PADDLE_ENFORCE_NE(ps,
delete_pass,
common::errors::InvalidArgument(
"Required ps shouldn't be equal to delete_pass. "));
}
}
#ifdef PADDLE_WITH_CRYPTO
TEST(paddle_inference_api, crypto) { paddle::MakeCipher(""); }
#endif
} // namespace paddle
+86
View File
@@ -0,0 +1,86 @@
/* 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. */
#pragma once
#include <ostream>
#include <string>
#include "paddle/fluid/inference/api/paddle_inference_api.h"
namespace paddle {
namespace inference {
thread_local int num_spaces = 0;
static std::string GenSpaces(int num_spaces) {
std::ostringstream os;
for (int i = 0; i < num_spaces; ++i) {
os << " ";
}
return os.str();
}
std::ostream &operator<<(std::ostream &os,
const PaddlePredictor::Config &config) {
os << GenSpaces(num_spaces) << "PaddlePredictor::Config {\n";
num_spaces++;
os << GenSpaces(num_spaces) << "model_dir: " << config.model_dir << "\n";
num_spaces--;
os << GenSpaces(num_spaces) << "}\n";
return os;
}
std::ostream &operator<<(std::ostream &os, const NativeConfig &config) {
os << GenSpaces(num_spaces) << "NativeConfig {\n";
num_spaces++;
os << *reinterpret_cast<const PaddlePredictor::Config *>(&config);
os << GenSpaces(num_spaces) << "use_gpu: " << config.use_gpu << "\n";
os << GenSpaces(num_spaces) << "device: " << config.device << "\n";
os << GenSpaces(num_spaces)
<< "fraction_of_gpu_memory: " << config.fraction_of_gpu_memory << "\n";
os << GenSpaces(num_spaces)
<< "specify_input_name: " << config.specify_input_name << "\n";
num_spaces--;
os << GenSpaces(num_spaces) << "}\n";
return os;
}
std::ostream &operator<<(std::ostream &os, const AnalysisConfig &config) {
os << GenSpaces(num_spaces) << "AnalysisConfig {\n";
num_spaces++;
os << config.ToNativeConfig();
if (!config.model_from_memory()) {
os << GenSpaces(num_spaces) << "prog_file: " << config.prog_file() << "\n";
os << GenSpaces(num_spaces) << "param_file: " << config.params_file()
<< "\n";
} else {
os << GenSpaces(num_spaces)
<< "prog_file and param_file: load from memory \n";
}
os << GenSpaces(num_spaces) << "enable_ir_optim: " << config.ir_optim()
<< "\n";
os << GenSpaces(num_spaces)
<< "cpu_num_threads: " << config.cpu_math_library_num_threads() << "\n";
os << GenSpaces(num_spaces)
<< "use_tensorrt: " << config.tensorrt_engine_enabled() << "\n";
os << GenSpaces(num_spaces) << "use_onednn: " << config.onednn_enabled()
<< "\n";
num_spaces--;
os << GenSpaces(num_spaces) << "}\n";
return os;
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,275 @@
# 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.
import argparse
import io
import os
import shutil
import sys
import tarfile
import numpy as np
from PIL import Image
from paddle.dataset.common import download
np.random.seed(0)
DATA_DIM = 224
SIZE_FLOAT32 = 4
SIZE_INT64 = 8
FULL_SIZE_BYTES = 30106000008
FULL_IMAGES = 50000
FOLDER_NAME = "ILSVRC2012/"
VALLIST_TAR_NAME = "ILSVRC2012/val_list.txt"
img_mean = np.array([0.485, 0.456, 0.406]).reshape((3, 1, 1))
img_std = np.array([0.229, 0.224, 0.225]).reshape((3, 1, 1))
def resize_short(img, target_size):
percent = float(target_size) / min(img.size[0], img.size[1])
resized_width = int(round(img.size[0] * percent))
resized_height = int(round(img.size[1] * percent))
img = img.resize((resized_width, resized_height), Image.LANCZOS)
return img
def crop_image(img, target_size, center):
width, height = img.size
size = target_size
if center:
w_start = (width - size) // 2
h_start = (height - size) // 2
else:
w_start = np.random.randint(0, width - size + 1)
h_start = np.random.randint(0, height - size + 1)
w_end = w_start + size
h_end = h_start + size
img = img.crop((w_start, h_start, w_end, h_end))
return img
def process_image(img):
img = resize_short(img, target_size=256)
img = crop_image(img, target_size=DATA_DIM, center=True)
if img.mode != 'RGB':
img = img.convert('RGB')
img = np.array(img).astype('float32').transpose((2, 0, 1)) / 255
img -= img_mean
img /= img_std
return img
def download_concat(cache_folder, zip_path):
data_urls = []
data_md5s = []
data_urls.append(
'https://paddle-inference-dist.bj.bcebos.com/int8/ILSVRC2012_img_val.tar.gz.partaa'
)
data_md5s.append('60f6525b0e1d127f345641d75d41f0a8')
data_urls.append(
'https://paddle-inference-dist.bj.bcebos.com/int8/ILSVRC2012_img_val.tar.gz.partab'
)
data_md5s.append('1e9f15f64e015e58d6f9ec3210ed18b5')
file_names = []
print("Downloading full ImageNet Validation dataset ...")
for i in range(0, len(data_urls)):
download(data_urls[i], cache_folder, data_md5s[i])
file_name = os.path.join(cache_folder, data_urls[i].split('/')[-1])
file_names.append(file_name)
print(f"Downloaded part {file_name}\n")
with open(zip_path, "wb") as outfile:
for fname in file_names:
shutil.copyfileobj(open(fname, 'rb'), outfile)
def print_processbar(done_percentage):
done_filled = done_percentage * '='
empty_filled = (100 - done_percentage) * ' '
sys.stdout.write(f"\r[{done_filled}{empty_filled}]{done_percentage}%")
sys.stdout.flush()
def convert_Imagenet_tar2bin(tar_file, output_file):
print('Converting 50000 images to binary file ...\n')
tar = tarfile.open(name=tar_file, mode='r:gz')
print_processbar(0)
dataset = {}
for tarInfo in tar:
if tarInfo.isfile() and tarInfo.name != VALLIST_TAR_NAME:
dataset[tarInfo.name] = tar.extractfile(tarInfo).read()
with open(output_file, "w+b") as ofs:
ofs.seek(0)
num = np.array(int(FULL_IMAGES)).astype('int64')
ofs.write(num.tobytes())
per_percentage = FULL_IMAGES // 100
val_info = tar.getmember(VALLIST_TAR_NAME)
val_list = tar.extractfile(val_info).read().decode("utf-8")
lines = val_list.splitlines()
idx = 0
for imagedata in dataset.values():
img = Image.open(io.BytesIO(imagedata))
img = process_image(img)
np_img = np.array(img)
ofs.write(np_img.astype('float32').tobytes())
if idx % per_percentage == 0:
print_processbar(idx // per_percentage)
idx = idx + 1
val_dict = {}
for line_idx, line in enumerate(lines):
if line_idx == FULL_IMAGES:
break
name, label = line.split()
val_dict[name] = label
for img_name in dataset.keys():
remove_len = len(FOLDER_NAME)
img_name_prim = img_name[remove_len:]
label = val_dict[img_name_prim]
label_int = (int)(label)
np_label = np.array(label_int)
ofs.write(np_label.astype('int64').tobytes())
print_processbar(100)
tar.close()
print("Conversion finished.")
def run_convert():
print('Start to download and convert 50000 images to binary file...')
cache_folder = os.path.expanduser('~/.cache/paddle/dataset/int8/download')
zip_path = os.path.join(cache_folder, 'full_imagenet_val.tar.gz.partaa')
output_file = os.path.join(cache_folder, 'int8_full_val.bin')
retry = 0
try_limit = 3
while not (
os.path.exists(output_file)
and os.path.getsize(output_file) == FULL_SIZE_BYTES
):
if os.path.exists(output_file):
sys.stderr.write(
f"\n\nThe existing binary file[{output_file}] is broken. Start to generate new one...\n\n"
)
os.remove(output_file)
if retry < try_limit:
retry = retry + 1
else:
raise RuntimeError(
f"Can not convert the dataset to binary file with try limit {try_limit}"
)
download_concat(cache_folder, zip_path)
convert_Imagenet_tar2bin(zip_path, output_file)
print(f"\nSuccess! The binary file can be found at {output_file}")
def convert_Imagenet_local2bin(args):
data_dir = args.data_dir
label_list_path = os.path.join(args.data_dir, args.label_list)
bin_file_path = os.path.join(args.data_dir, args.output_file)
assert data_dir, 'Once set --local, user need to provide the --data_dir'
with open(label_list_path) as flist:
lines = [line.strip() for line in flist]
num_images = len(lines)
with open(bin_file_path, "w+b") as of:
of.seek(0)
num = np.array(int(num_images)).astype('int64')
of.write(num.tobytes())
for idx, line in enumerate(lines):
img_path, label = line.split()
img_path = os.path.join(data_dir, img_path)
if not os.path.exists(img_path):
continue
# save image(float32) to file
img = Image.open(img_path)
img = process_image(img)
np_img = np.array(img)
of.seek(
SIZE_INT64 + SIZE_FLOAT32 * DATA_DIM * DATA_DIM * 3 * idx
)
of.write(np_img.astype('float32').tobytes())
# save label(int64_t) to file
label_int = (int)(label)
np_label = np.array(label_int)
of.seek(
SIZE_INT64
+ SIZE_FLOAT32 * DATA_DIM * DATA_DIM * 3 * num_images
+ idx * SIZE_INT64
)
of.write(np_label.astype('int64').tobytes())
# The bin file should contain
# number of images + all images data + all corresponding labels
# so the file target_size should be as follows
target_size = (
SIZE_INT64
+ num_images * 3 * args.data_dim * args.data_dim * SIZE_FLOAT32
+ num_images * SIZE_INT64
)
if os.path.getsize(bin_file_path) == target_size:
print(
f"Success! The user data output binary file can be found at: {bin_file_path}"
)
else:
print("Conversion failed!")
def main_preprocess_Imagenet(args):
parser = argparse.ArgumentParser(
description="Convert the full Imagenet val set or local data to binary file.",
usage=None,
add_help=True,
)
parser.add_argument(
'--local',
action="store_true",
help="If used, user need to set --data_dir and then convert file",
)
parser.add_argument(
"--data_dir", default="", type=str, help="Dataset root directory"
)
parser.add_argument(
"--label_list",
type=str,
default="val_list.txt",
help="List of object labels with same sequence as denoted in the annotation file",
)
parser.add_argument(
"--output_file",
type=str,
default="imagenet_small.bin",
help="File path of the output binary file",
)
parser.add_argument(
"--data_dim",
type=int,
default=DATA_DIM,
help="Image preprocess with data_dim width and height",
)
args = parser.parse_args()
if args.local:
convert_Imagenet_local2bin(args)
else:
run_convert()
if __name__ == '__main__':
main_preprocess_Imagenet(sys.argv)
@@ -0,0 +1,373 @@
# 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.
import argparse
import hashlib
import os
import sys
import tarfile
import xml.etree.ElementTree
from io import StringIO
import numpy as np
from PIL import Image
from paddle.dataset.common import download
DATA_URL = (
"http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar"
)
DATA_DIR = os.path.expanduser("~/.cache/paddle/dataset/pascalvoc/")
TAR_FILE = "VOCtest_06-Nov-2007.tar"
TAR_PATH = os.path.join(DATA_DIR, TAR_FILE)
SIZE_FLOAT32 = 4
SIZE_INT64 = 8
RESIZE_H = 300
RESIZE_W = 300
MEAN_VALUE = [127.5, 127.5, 127.5]
AP_VERSION = '11point'
DATA_OUT = 'pascalvoc_full.bin'
DATA_OUT_PATH = os.path.join(DATA_DIR, DATA_OUT)
BIN_TARGETHASH = "f6546cadc42f5ff13178b84ed29b740b"
TAR_TARGETHASH = "b6e924de25625d8de591ea690078ad9f"
TEST_LIST_KEY = "VOCdevkit/VOC2007/ImageSets/Main/test.txt"
BIN_FULLSIZE = 5348678856
def preprocess(img):
img_width, img_height = img.size
img = img.resize((RESIZE_W, RESIZE_H), Image.LANCZOS)
img = np.array(img)
# HWC to CHW
if len(img.shape) == 3:
img = np.swapaxes(img, 1, 2)
img = np.swapaxes(img, 1, 0)
# RBG to BGR
img = img[[2, 1, 0], :, :]
img = img.astype('float32')
img_mean = np.array(MEAN_VALUE)[:, np.newaxis, np.newaxis].astype('float32')
img -= img_mean
img = img * 0.007843
return img
def convert_pascalvoc_local2bin(args):
data_dir = os.path.expanduser(args.data_dir)
label_fpath = os.path.join(data_dir, args.label_file)
assert data_dir, 'Once set --local, user need to provide the --data_dir'
flabel = open(label_fpath)
label_list = [line.strip() for line in flabel]
img_annotation_list_path = os.path.join(data_dir, args.img_annotation_list)
flist = open(img_annotation_list_path)
lines = [line.strip() for line in flist]
output_file_path = os.path.join(data_dir, args.output_file)
f1 = open(output_file_path, "w+b")
f1.seek(0)
image_nums = len(lines)
f1.write(np.array(image_nums).astype('int64').tobytes())
boxes = []
lbls = []
difficulties = []
object_nums = []
for line in lines:
image_path, label_path = line.split()
image_path = os.path.join(data_dir, image_path)
label_path = os.path.join(data_dir, label_path)
im = Image.open(image_path)
if im.mode == 'L':
im = im.convert('RGB')
im_width, im_height = im.size
im = preprocess(im)
np_im = np.array(im)
f1.write(np_im.astype('float32').tobytes())
# layout: label | xmin | ymin | xmax | ymax | difficult
bbox_labels = []
root = xml.etree.ElementTree.parse(label_path).getroot()
objects = root.findall('object')
objects_size = len(objects)
object_nums.append(objects_size)
for object in objects:
bbox_sample = []
# start from 1
bbox_sample.append(
float(label_list.index(object.find('name').text))
)
bbox = object.find('bndbox')
difficult = float(object.find('difficult').text)
bbox_sample.append(float(bbox.find('xmin').text) / im_width)
bbox_sample.append(float(bbox.find('ymin').text) / im_height)
bbox_sample.append(float(bbox.find('xmax').text) / im_width)
bbox_sample.append(float(bbox.find('ymax').text) / im_height)
bbox_sample.append(difficult)
bbox_labels.append(bbox_sample)
bbox_labels = np.array(bbox_labels)
if len(bbox_labels) == 0:
continue
lbls.extend(bbox_labels[:, 0])
boxes.extend(bbox_labels[:, 1:5])
difficulties.extend(bbox_labels[:, -1])
f1.write(np.array(object_nums).astype('uint64').tobytes())
f1.write(np.array(lbls).astype('int64').tobytes())
f1.write(np.array(boxes).astype('float32').tobytes())
f1.write(np.array(difficulties).astype('int64').tobytes())
f1.close()
object_nums_sum = sum(object_nums)
# The data should be contains
# number of images + all images data + an array that represent object numbers of each image
# + labels of all objects in images + bboxes of all objects + difficulties of all objects
# so the target size should be as follows:
target_size = (
SIZE_INT64
+ image_nums * 3 * args.resize_h * args.resize_h * SIZE_FLOAT32
+ image_nums * SIZE_INT64
+ object_nums_sum * (SIZE_INT64 + 4 * SIZE_FLOAT32 + SIZE_INT64)
)
if os.path.getsize(output_file_path) == target_size:
print(
"Success! \nThe local data output binary file can be found at: ",
output_file_path,
)
else:
print("Conversion failed!")
def print_processbar(done_percentage):
done_filled = done_percentage * '='
empty_filled = (100 - done_percentage) * ' '
sys.stdout.write(f"\r[{done_filled}{empty_filled}]{done_percentage}%")
sys.stdout.flush()
def convert_pascalvoc_tar2bin(tar_path, data_out_path):
print("Start converting ...\n")
images = {}
gt_labels = {}
boxes = []
lbls = []
difficulties = []
object_nums = []
# map label to number (index)
label_list = [
"background",
"aeroplane",
"bicycle",
"bird",
"boat",
"bottle",
"bus",
"car",
"cat",
"chair",
"cow",
"diningtable",
"dog",
"horse",
"motorbike",
"person",
"pottedplant",
"sheep",
"sofa",
"train",
"tvmonitor",
]
print_processbar(0)
# read from tar file and write to bin
tar = tarfile.open(tar_path, "r")
f_test = tar.extractfile(TEST_LIST_KEY).read()
lines = f_test.split('\n')
del lines[-1]
image_nums = len(lines)
per_percentage = image_nums / 100
f1 = open(data_out_path, "w+b")
f1.seek(0)
f1.write(np.array(image_nums).astype('int64').tobytes())
for tarInfo in tar:
if tarInfo.isfile():
tmp_filename = tarInfo.name
name_arr = tmp_filename.split('/')
name_prefix = name_arr[-1].split('.')[0]
if name_arr[-2] == 'JPEGImages' and name_prefix in lines:
images[name_prefix] = tar.extractfile(tarInfo).read()
if name_arr[-2] == 'Annotations' and name_prefix in lines:
gt_labels[name_prefix] = tar.extractfile(tarInfo).read()
for line_idx, name_prefix in enumerate(lines):
im = Image.open(StringIO(images[name_prefix]))
if im.mode == 'L':
im = im.convert('RGB')
im_width, im_height = im.size
im = preprocess(im)
np_im = np.array(im)
f1.write(np_im.astype('float32').tobytes())
# layout: label | xmin | ymin | xmax | ymax | difficult
bbox_labels = []
root = xml.etree.ElementTree.fromstring(gt_labels[name_prefix])
objects = root.findall('object')
objects_size = len(objects)
object_nums.append(objects_size)
for object in objects:
bbox_sample = []
bbox_sample.append(
float(label_list.index(object.find('name').text))
)
bbox = object.find('bndbox')
difficult = float(object.find('difficult').text)
bbox_sample.append(float(bbox.find('xmin').text) / im_width)
bbox_sample.append(float(bbox.find('ymin').text) / im_height)
bbox_sample.append(float(bbox.find('xmax').text) / im_width)
bbox_sample.append(float(bbox.find('ymax').text) / im_height)
bbox_sample.append(difficult)
bbox_labels.append(bbox_sample)
bbox_labels = np.array(bbox_labels)
if len(bbox_labels) == 0:
continue
lbls.extend(bbox_labels[:, 0])
boxes.extend(bbox_labels[:, 1:5])
difficulties.extend(bbox_labels[:, -1])
if line_idx % per_percentage:
print_processbar(line_idx / per_percentage)
# The data should be stored in binary in following sequence:
# number of images->all images data->an array that represent object numbers in each image
# ->labels of all objects in images->bboxes of all objects->difficulties of all objects
f1.write(np.array(object_nums).astype('uint64').tobytes())
f1.write(np.array(lbls).astype('int64').tobytes())
f1.write(np.array(boxes).astype('float32').tobytes())
f1.write(np.array(difficulties).astype('int64').tobytes())
f1.close()
print_processbar(100)
print("Conversion finished!\n")
def download_pascalvoc(data_url, data_dir, tar_targethash, tar_path):
print("Downloading pascalvcoc test set...")
download(data_url, data_dir, tar_targethash)
if not os.path.exists(tar_path):
print(f"Failed in downloading pascalvoc test set. URL {data_url}\n")
else:
tmp_hash = hashlib.md5(open(tar_path, 'rb').read()).hexdigest()
if tmp_hash != tar_targethash:
print("Downloaded test set is broken, removing ...\n")
else:
print(f"Downloaded successfully. Path: {tar_path}\n")
def run_convert():
try_limit = 2
retry = 0
while not (
os.path.exists(DATA_OUT_PATH)
and os.path.getsize(DATA_OUT_PATH) == BIN_FULLSIZE
and BIN_TARGETHASH
== hashlib.md5(open(DATA_OUT_PATH, 'rb').read()).hexdigest()
):
if os.path.exists(DATA_OUT_PATH):
sys.stderr.write(
"The existing binary file is broken. It is being removed...\n"
)
os.remove(DATA_OUT_PATH)
if retry < try_limit:
retry = retry + 1
else:
download_pascalvoc(DATA_URL, DATA_DIR, TAR_TARGETHASH, TAR_PATH)
convert_pascalvoc_tar2bin(TAR_PATH, DATA_OUT_PATH)
print(f"Success!\nThe binary file can be found at {DATA_OUT_PATH}\n")
def main_pascalvoc_preprocess(args):
parser = argparse.ArgumentParser(
description="Convert the full pascalvoc val set or local data to binary file.",
usage=None,
add_help=True,
)
parser.add_argument(
'--local',
action="store_true",
help="If used, user need to set --data_dir and then convert file",
)
parser.add_argument(
"--data_dir", default="", type=str, help="Dataset root directory"
)
parser.add_argument(
"--img_annotation_list",
type=str,
default="test_100.txt",
help="A file containing the image file path and corresponding annotation file path",
)
parser.add_argument(
"--label_file",
type=str,
default="label_list",
help="List of object labels with same sequence as denoted in the annotation file",
)
parser.add_argument(
"--output_file",
type=str,
default="pascalvoc_small.bin",
help="File path of the output binary file",
)
parser.add_argument(
"--resize_h",
type=int,
default=RESIZE_H,
help="Image preprocess with resize_h",
)
parser.add_argument(
"--resize_w",
type=int,
default=RESIZE_W,
help="Image prerocess with resize_w",
)
parser.add_argument(
"--mean_value",
type=str,
default=MEAN_VALUE,
help="Image preprocess with mean_value",
)
parser.add_argument(
"--ap_version",
type=str,
default=AP_VERSION,
help="Image preprocess with ap_version",
)
args = parser.parse_args()
if args.local:
convert_pascalvoc_local2bin(args)
else:
run_convert()
if __name__ == "__main__":
main_pascalvoc_preprocess(sys.argv)
@@ -0,0 +1,290 @@
// Copyright (c) 2022 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/api/paddle_inference_api.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
using paddle::PaddleTensor;
template <typename T>
void GetValueFromStream(std::stringstream *ss, T *t) {
(*ss) >> (*t);
}
template <>
void GetValueFromStream<std::string>(std::stringstream *ss, std::string *t) {
*t = ss->str();
}
// Split string to vector
template <typename T>
void Split(const std::string &line, char sep, std::vector<T> *v) {
std::stringstream ss;
T t;
for (auto c : line) {
if (c != sep) {
ss << c;
} else {
GetValueFromStream<T>(&ss, &t);
v->push_back(std::move(t));
ss.str({});
ss.clear();
}
}
if (!ss.str().empty()) {
GetValueFromStream<T>(&ss, &t);
v->push_back(std::move(t));
ss.str({});
ss.clear();
}
}
// Parse tensor from string
template <typename T>
bool ParseTensor(const std::string &field, paddle::PaddleTensor *tensor) {
std::vector<std::string> data;
Split(field, ':', &data);
if (data.size() < 2) return false;
std::string shape_str = data[0];
std::vector<int> shape;
Split(shape_str, ' ', &shape);
std::string mat_str = data[1];
std::vector<T> mat;
Split(mat_str, ' ', &mat);
tensor->shape = shape;
auto size =
std::accumulate(shape.begin(), shape.end(), 1, std::multiplies<int>()) *
sizeof(T);
tensor->data.Resize(size);
std::copy(mat.begin(), mat.end(), static_cast<T *>(tensor->data.data()));
tensor->dtype = GetPaddleDType<T>();
return true;
}
// Parse input tensors from string
bool ParseLine(const std::string &line,
std::vector<paddle::PaddleTensor> *tensors) {
std::vector<std::string> fields;
Split(line, ';', &fields);
tensors->clear();
tensors->reserve(4);
int i = 0;
auto input_name = FLAGS_ernie_large ? "eval_placeholder_" : "placeholder_";
for (; i < 3; i++) {
paddle::PaddleTensor temp;
ParseTensor<int64_t>(fields[i], &temp);
temp.name = input_name + std::to_string(i);
tensors->push_back(temp);
}
// input_mask
paddle::PaddleTensor input_mask;
ParseTensor<float>(fields[i], &input_mask);
input_mask.name = input_name + std::to_string(i);
tensors->push_back(input_mask);
return true;
}
bool LoadInputData(std::vector<std::vector<paddle::PaddleTensor>> *inputs,
int batch_size = 1) {
if (FLAGS_infer_data.empty()) {
LOG(ERROR) << "please set input data path";
return false;
}
std::ifstream fin(FLAGS_infer_data);
std::string line;
int sample = 0;
// The unit-test dataset only have 10 samples, each sample have 5 feeds.
while (std::getline(fin, line)) {
std::vector<paddle::PaddleTensor> feed_data;
ParseLine(line, &feed_data);
inputs->push_back(std::move(feed_data));
sample++;
if (!FLAGS_test_all_data && sample == batch_size) break;
}
LOG(INFO) << "number of samples: " << sample;
return true;
}
// Compare results
TEST(Ernie_gpu_fp16_no_ir, compare_results) {
AnalysisConfig config;
config.SetModel(FLAGS_infer_model);
config.EnableUseGpu(512, 0, paddle_infer::PrecisionType::kHalf);
config.SwitchIrOptim(false);
auto predictor = CreatePaddlePredictor(config);
std::vector<std::vector<PaddleTensor>> input_slots_all;
LoadInputData(&input_slots_all);
std::ifstream fin(FLAGS_refer_result);
std::string line;
std::vector<float> ref;
while (std::getline(fin, line)) {
Split(line, ' ', &ref);
}
std::vector<PaddleTensor> outputs;
for (size_t i = 0; i < input_slots_all.size(); i++) {
outputs.clear();
predictor->Run(input_slots_all[i], &outputs);
auto output = outputs.front();
size_t outputs_size = 1;
for (auto dim : output.shape) {
outputs_size *= dim;
}
float *result = reinterpret_cast<float *>(output.data.data());
for (size_t j = 0; j < outputs_size; ++j) {
EXPECT_NEAR(ref[i * outputs_size + j], result[j], 8e-3);
}
}
}
// Compare results
TEST(Ernie_gpu_fp16_with_ir, compare_results) {
AnalysisConfig config;
config.SetModel(FLAGS_infer_model);
config.EnableUseGpu(512, 0, paddle_infer::PrecisionType::kHalf);
config.SwitchIrOptim(true);
// There is a problem with the model itself, which has nothing to do with
// constant_folding_pass.
config.pass_builder()->DeletePass("constant_folding_pass");
auto predictor = CreatePaddlePredictor(config);
std::vector<std::vector<PaddleTensor>> input_slots_all;
LoadInputData(&input_slots_all);
std::ifstream fin(FLAGS_refer_result);
std::string line;
std::vector<float> ref;
while (std::getline(fin, line)) {
Split(line, ' ', &ref);
}
std::vector<PaddleTensor> outputs;
for (size_t i = 0; i < input_slots_all.size(); i++) {
outputs.clear();
predictor->Run(input_slots_all[i], &outputs);
auto output = outputs.front();
size_t outputs_size = 1;
for (auto dim : output.shape) {
outputs_size *= dim;
}
float *result = reinterpret_cast<float *>(output.data.data());
for (size_t j = 0; j < outputs_size; ++j) {
EXPECT_NEAR(ref[i * outputs_size + j], result[j], 2e-2);
}
}
}
// Compare results
TEST(Ernie_gpu_bf16_no_ir, compare_results) {
AnalysisConfig config;
config.SetModel(FLAGS_infer_model);
config.EnableUseGpu(512, 0, paddle_infer::PrecisionType::kBf16);
config.SwitchIrOptim(false);
auto predictor = CreatePaddlePredictor(config);
std::vector<std::vector<PaddleTensor>> input_slots_all;
LoadInputData(&input_slots_all);
std::ifstream fin(FLAGS_refer_result);
std::string line;
std::vector<float> ref;
while (std::getline(fin, line)) {
Split(line, ' ', &ref);
}
std::vector<PaddleTensor> outputs;
for (size_t i = 0; i < input_slots_all.size(); i++) {
outputs.clear();
predictor->Run(input_slots_all[i], &outputs);
auto output = outputs.front();
size_t outputs_size = 1;
for (auto dim : output.shape) {
outputs_size *= dim;
}
float *result = reinterpret_cast<float *>(output.data.data());
for (size_t j = 0; j < outputs_size; ++j) {
EXPECT_NEAR(ref[i * outputs_size + j], result[j], 1e-2);
}
}
}
// Compare results
TEST(Ernie_gpu_bf16_with_ir, compare_results) {
AnalysisConfig config;
config.SetModel(FLAGS_infer_model);
config.EnableUseGpu(512, 0, paddle_infer::PrecisionType::kBf16);
config.SwitchIrOptim(true);
// There is a problem with the model itself, which has nothing to do with
// constant_folding_pass.
config.pass_builder()->DeletePass("constant_folding_pass");
auto predictor = CreatePaddlePredictor(config);
std::vector<std::vector<PaddleTensor>> input_slots_all;
LoadInputData(&input_slots_all);
std::ifstream fin(FLAGS_refer_result);
std::string line;
std::vector<float> ref;
while (std::getline(fin, line)) {
Split(line, ' ', &ref);
}
std::vector<PaddleTensor> outputs;
for (size_t i = 0; i < input_slots_all.size(); i++) {
outputs.clear();
predictor->Run(input_slots_all[i], &outputs);
auto output = outputs.front();
size_t outputs_size = 1;
for (auto dim : output.shape) {
outputs_size *= dim;
}
float *result = reinterpret_cast<float *>(output.data.data());
for (size_t j = 0; j < outputs_size; ++j) {
EXPECT_NEAR(ref[i * outputs_size + j], result[j], 5e-3);
}
}
}
} // namespace inference
} // namespace paddle
+35
View File
@@ -0,0 +1,35 @@
/* Copyright (c) 2022 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/api/helper.h"
#include "gtest/gtest.h"
namespace paddle {
TEST(inference_api_helper, DataType) {
ASSERT_TRUE(
paddle::inference::IsFloatVar(paddle::framework::proto::VarType::FP64));
ASSERT_TRUE(
paddle::inference::IsFloatVar(paddle::framework::proto::VarType::FP32));
ASSERT_TRUE(
paddle::inference::IsFloatVar(paddle::framework::proto::VarType::FP16));
ASSERT_TRUE(
paddle::inference::IsFloatVar(paddle::framework::proto::VarType::BF16));
ASSERT_FALSE(
paddle::inference::IsFloatVar(paddle::framework::proto::VarType::INT32));
}
} // namespace paddle
@@ -0,0 +1,184 @@
// Copyright (c) 2022 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 "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
using paddle::PaddleTensor;
template <typename T>
void GetValueFromStream(std::stringstream *ss, T *t) {
(*ss) >> (*t);
}
template <>
void GetValueFromStream<std::string>(std::stringstream *ss, std::string *t) {
*t = ss->str();
}
// Split string to vector
template <typename T>
void Split(const std::string &line, char sep, std::vector<T> *v) {
std::stringstream ss;
T t;
for (auto c : line) {
if (c != sep) {
ss << c;
} else {
GetValueFromStream<T>(&ss, &t);
v->push_back(std::move(t));
ss.str({});
ss.clear();
}
}
if (!ss.str().empty()) {
GetValueFromStream<T>(&ss, &t);
v->push_back(std::move(t));
ss.str({});
ss.clear();
}
}
// Parse tensor from string
template <typename T>
bool ParseTensor(const std::string &field, paddle::PaddleTensor *tensor) {
std::vector<std::string> data;
Split(field, ':', &data);
if (data.size() < 2) return false;
std::string shape_str = data[0];
std::vector<int> shape;
Split(shape_str, ' ', &shape);
std::string mat_str = data[1];
std::vector<T> mat;
Split(mat_str, ' ', &mat);
tensor->shape = shape;
auto size =
std::accumulate(shape.begin(), shape.end(), 1, std::multiplies<int>()) *
sizeof(T);
tensor->data.Resize(size);
std::copy(mat.begin(), mat.end(), static_cast<T *>(tensor->data.data()));
tensor->dtype = GetPaddleDType<T>();
return true;
}
// Parse input tensors from string
bool ParseLine(const std::string &line,
std::vector<paddle::PaddleTensor> *tensors) {
std::vector<std::string> fields;
Split(line, ';', &fields);
tensors->clear();
tensors->reserve(4);
int i = 0;
auto input_name = FLAGS_ernie_large ? "eval_placeholder_" : "placeholder_";
for (; i < 3; i++) {
paddle::PaddleTensor temp;
ParseTensor<int64_t>(fields[i], &temp);
temp.name = input_name + std::to_string(i);
tensors->push_back(temp);
}
// input_mask
paddle::PaddleTensor input_mask;
ParseTensor<float>(fields[i], &input_mask);
// fp32 to fp16
ConvertFP32toFP16(input_mask);
input_mask.name = input_name + std::to_string(i);
tensors->push_back(input_mask);
return true;
}
bool LoadInputData(std::vector<std::vector<paddle::PaddleTensor>> *inputs,
int batch_size = 1) {
if (FLAGS_infer_data.empty()) {
LOG(ERROR) << "please set input data path";
return false;
}
std::ifstream fin(FLAGS_infer_data);
std::string line;
int sample = 0;
// The unit-test dataset only have 10 samples, each sample have 5 feeds.
while (std::getline(fin, line)) {
std::vector<paddle::PaddleTensor> feed_data;
ParseLine(line, &feed_data);
inputs->push_back(std::move(feed_data));
sample++;
if (!FLAGS_test_all_data && sample == batch_size) break;
}
LOG(INFO) << "number of samples: " << sample;
return true;
}
void SetConfig(AnalysisConfig *cfg, int batch_size = 1) {
cfg->SetModel(FLAGS_infer_model);
// ipu_device_num, ipu_micro_batch_size, ipu_enable_pipelining
cfg->EnableIpu(1, batch_size, false);
// ipu_enable_fp16, ipu_replica_num, ipu_available_memory_proportion,
// ipu_enable_half_partial
cfg->SetIpuConfig(true, 1, 1.0, true);
}
// Compare results
TEST(Analyzer_Ernie_ipu, compare_results) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
LoadInputData(&input_slots_all);
std::ifstream fin(FLAGS_refer_result);
std::string line;
std::vector<float> ref;
while (std::getline(fin, line)) {
Split(line, ' ', &ref);
}
auto predictor = CreateTestPredictor(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
FLAGS_use_analysis);
std::vector<PaddleTensor> outputs;
for (size_t i = 0; i < input_slots_all.size(); i++) {
outputs.clear();
predictor->Run(input_slots_all[i], &outputs);
auto output = outputs.front();
ConvertFP16toFP32(output);
auto outputs_size = 1;
for (auto dim : output.shape) {
outputs_size *= dim;
}
float *fp32_data = reinterpret_cast<float *>(output.data.data());
for (size_t j = 0; j < outputs_size; ++j) {
EXPECT_NEAR(ref[i * outputs_size + j], fp32_data[j], 5e-3);
}
}
}
} // namespace inference
} // namespace paddle
+198
View File
@@ -0,0 +1,198 @@
// Copyright (c) 2022 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 "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
using paddle::PaddleTensor;
template <typename T>
void GetValueFromStream(std::stringstream *ss, T *t) {
(*ss) >> (*t);
}
template <>
void GetValueFromStream<std::string>(std::stringstream *ss, std::string *t) {
*t = ss->str();
}
// Split string to vector
template <typename T>
void Split(const std::string &line, char sep, std::vector<T> *v) {
std::stringstream ss;
T t;
for (auto c : line) {
if (c != sep) {
ss << c;
} else {
GetValueFromStream<T>(&ss, &t);
v->push_back(std::move(t));
ss.str({});
ss.clear();
}
}
if (!ss.str().empty()) {
GetValueFromStream<T>(&ss, &t);
v->push_back(std::move(t));
ss.str({});
ss.clear();
}
}
// Parse tensor from string
template <typename T>
bool ParseTensor(const std::string &field, paddle::PaddleTensor *tensor) {
std::vector<std::string> data;
Split(field, ':', &data);
if (data.size() < 2) return false;
std::string shape_str = data[0];
std::vector<int> shape;
Split(shape_str, ' ', &shape);
std::string mat_str = data[1];
std::vector<T> mat;
Split(mat_str, ' ', &mat);
tensor->shape = shape;
auto size =
std::accumulate(shape.begin(), shape.end(), 1, std::multiplies<int>()) *
sizeof(T);
tensor->data.Resize(size);
std::copy(mat.begin(), mat.end(), static_cast<T *>(tensor->data.data()));
tensor->dtype = GetPaddleDType<T>();
return true;
}
// Parse input tensors from string
bool ParseLine(const std::string &line,
std::vector<paddle::PaddleTensor> *tensors) {
std::vector<std::string> fields;
Split(line, ';', &fields);
tensors->clear();
tensors->reserve(4);
int i = 0;
auto input_name = FLAGS_ernie_large ? "eval_placeholder_" : "placeholder_";
for (; i < 3; i++) {
paddle::PaddleTensor temp;
ParseTensor<int64_t>(fields[i], &temp);
temp.name = input_name + std::to_string(i);
tensors->push_back(temp);
}
// input_mask
paddle::PaddleTensor input_mask;
ParseTensor<float>(fields[i], &input_mask);
input_mask.name = input_name + std::to_string(i);
tensors->push_back(input_mask);
return true;
}
bool LoadInputData(std::vector<std::vector<paddle::PaddleTensor>> *inputs,
int batch_size = 1) {
if (FLAGS_infer_data.empty()) {
LOG(ERROR) << "please set input data path";
return false;
}
std::ifstream fin(FLAGS_infer_data);
std::string line;
int sample = 0;
// The unit-test dataset only have 10 samples, each sample have 5 feeds.
while (std::getline(fin, line)) {
std::vector<paddle::PaddleTensor> feed_data;
ParseLine(line, &feed_data);
inputs->push_back(std::move(feed_data));
sample++;
if (!FLAGS_test_all_data && sample == batch_size) break;
}
LOG(INFO) << "number of samples: " << sample;
return true;
}
void SetConfig(AnalysisConfig *cfg, int batch_size = 1) {
cfg->SetModel(FLAGS_infer_model);
// ipu_device_num, ipu_micro_batch_size, ipu_enable_pipelining
cfg->EnableIpu(1, batch_size, false);
}
void profile() {
AnalysisConfig config;
SetConfig(&config);
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<std::vector<PaddleTensor>> inputs;
LoadInputData(&inputs);
TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&config),
inputs,
&outputs,
FLAGS_num_threads);
}
// Compare Deterministic result
TEST(Analyzer_Ernie_ipu, compare_determine) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
LoadInputData(&input_slots_all);
CompareDeterministic(reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
input_slots_all);
}
// Compare results
TEST(Analyzer_Ernie_ipu, compare_results) {
AnalysisConfig cfg;
SetConfig(&cfg);
std::vector<std::vector<PaddleTensor>> input_slots_all;
LoadInputData(&input_slots_all);
std::ifstream fin(FLAGS_refer_result);
std::string line;
std::vector<float> ref;
while (std::getline(fin, line)) {
Split(line, ' ', &ref);
}
auto predictor = CreateTestPredictor(
reinterpret_cast<const PaddlePredictor::Config *>(&cfg),
FLAGS_use_analysis);
std::vector<PaddleTensor> outputs;
for (size_t i = 0; i < input_slots_all.size(); i++) {
outputs.clear();
predictor->Run(input_slots_all[i], &outputs);
auto outputs_size = outputs.front().data.length() / (sizeof(float));
for (size_t j = 0; j < outputs_size; ++j) {
EXPECT_NEAR(ref[i * outputs_size + j],
static_cast<float *>(outputs[0].data.data())[j],
FLAGS_accuracy);
}
}
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,112 @@
/* Copyright (c) 2022 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 <glog/logging.h>
#include <gtest/gtest.h>
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
void ErnieInputData(const int &total_batch_size,
const bool enable_fp16,
std::vector<PaddleTensor> *inputs) {
const int input_num = total_batch_size * 128 * 1;
std::vector<int64_t> placeholder_012(input_num, 1);
std::vector<float> placeholder_3(input_num, 1);
for (int i = 0; i < 4; i++) {
PaddleTensor in;
in.name = "placeholder_" + std::to_string(i);
in.shape = {total_batch_size, 128, 1};
if (i < 3) {
in.data = PaddleBuf(static_cast<void *>(placeholder_012.data()),
input_num * sizeof(int64_t));
in.dtype = PaddleDType::INT64;
} else {
in.data = PaddleBuf(static_cast<void *>(placeholder_3.data()),
input_num * sizeof(float));
in.dtype = PaddleDType::FLOAT32;
if (enable_fp16) {
ConvertFP32toFP16(in);
}
}
inputs->push_back(std::move(in));
}
}
void Resnet50InputData(const int &total_batch_size,
const bool enable_fp16,
std::vector<paddle::PaddleTensor> *inputs) {
const int input_num = total_batch_size * 3 * 318 * 318;
std::vector<float> input(input_num, 1);
PaddleTensor in;
in.shape = {total_batch_size, 3, 318, 318};
in.data =
PaddleBuf(static_cast<void *>(input.data()), input_num * sizeof(float));
in.dtype = PaddleDType::FLOAT32;
if (enable_fp16) {
ConvertFP32toFP16(in);
}
inputs->push_back(std::move(in));
}
// performance profile
TEST(Analyzer_ipu_fp16, performance_profile) {
AnalysisConfig config;
std::vector<PaddleTensor> inputs;
std::vector<std::vector<PaddleTensor>> outputs;
int total_batch_size = FLAGS_ipu_micro_batch_size * FLAGS_ipu_replica_num;
if (FLAGS_ipu_enable_pipelining) {
// if device_num > 1 and pipelining is enabled, the total batch size =
// micro_batch_size * device_num(batches_per_step) * replica_num
total_batch_size = FLAGS_ipu_micro_batch_size * FLAGS_ipu_batches_per_step *
FLAGS_ipu_replica_num;
}
if (FLAGS_model_name == "Resnet50") {
config.SetModel(FLAGS_infer_model + "/model/model",
FLAGS_infer_model + "/model/params");
Resnet50InputData(total_batch_size, FLAGS_ipu_enable_fp16, &inputs);
} else if (FLAGS_model_name == "Ernie") {
config.SetModel(FLAGS_infer_model + "/model/");
ErnieInputData(total_batch_size, FLAGS_ipu_enable_fp16, &inputs);
} else {
PADDLE_THROW(common::errors::InvalidArgument(
"Only support Resnet50 and Ernie Currently"));
}
// ipu_device_num, ipu_micro_batch_size, ipu_enable_pipelining,
// ipu_batches_per_step
config.EnableIpu(FLAGS_ipu_device_num,
FLAGS_ipu_micro_batch_size,
FLAGS_ipu_enable_pipelining,
FLAGS_ipu_batches_per_step);
// ipu_enable_fp16, ipu_replica_num, ipu_available_memory_proportion,
// ipu_enable_half_partial
config.SetIpuConfig(FLAGS_ipu_enable_fp16,
FLAGS_ipu_replica_num,
FLAGS_ipu_available_memory_proportion,
FLAGS_ipu_enable_half_partial);
TestPrediction(reinterpret_cast<const PaddlePredictor::Config *>(&config),
{inputs},
&outputs,
1);
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,87 @@
/* Copyright (c) 2022 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <cmath>
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
// Compare results with 1 batch
TEST(Analyzer_Resnet50_ipu, compare_results_1_batch) {
std::string model_dir = FLAGS_infer_model + "/" + "model";
AnalysisConfig config;
// ipu_device_num, ipu_micro_batch_size, ipu_enable_pipelining
config.EnableIpu(1, 1, false);
// ipu_enable_fp16, ipu_replica_num, ipu_available_memory_proportion,
// ipu_enable_half_partial
config.SetIpuConfig(true, 1, 1.0, true);
config.SetModel(model_dir + "/model", model_dir + "/params");
std::vector<PaddleTensor> inputs;
auto predictor = CreatePaddlePredictor(config);
const int batch = 1;
const int channel = 3;
const int height = 318;
const int width = 318;
const int input_num = batch * channel * height * width;
std::vector<float> input(input_num, 1);
PaddleTensor in;
in.shape = {batch, channel, height, width};
in.data =
PaddleBuf(static_cast<void*>(input.data()), input_num * sizeof(float));
in.dtype = PaddleDType::FLOAT32;
ConvertFP32toFP16(in);
inputs.emplace_back(in);
std::vector<PaddleTensor> outputs;
ASSERT_TRUE(predictor->Run(inputs, &outputs));
const std::vector<float> truth_values = {
127.779f, 738.165f, 1013.22f, -438.17f, 366.401f, 927.659f,
736.222f, -633.684f, -329.927f, -430.155f, -633.062f, -146.548f,
-1324.28f, -1349.36f, -242.675f, 117.448f, -801.723f, -391.514f,
-404.818f, 454.16f, 515.48f, -133.031f, 69.293f, 590.096f,
-1434.69f, -1070.89f, 307.074f, 400.525f, -316.12f, -587.125f,
-161.056f, 800.363f, -96.4708f, 748.706f, 868.174f, -447.938f,
112.737f, 1127.2f, 47.4355f, 677.72f, 593.186f, -336.4f,
551.362f, 397.823f, 78.3979f, -715.398f, 405.969f, 404.256f,
246.019f, -8.42969f, 131.365f, -648.051f};
const size_t expected_size = 1;
EXPECT_EQ(outputs.size(), expected_size);
auto output = outputs.front();
ConvertFP16toFP32(output);
auto outputs_size = 1;
for (auto dim : output.shape) {
outputs_size *= dim;
}
float* fp32_data = reinterpret_cast<float*>(output.data.data());
for (size_t j = 0; j < outputs_size; j += 10) {
EXPECT_NEAR(
(fp32_data[j] - truth_values[j / 10]) / truth_values[j / 10], 0., 9e-2);
}
}
} // namespace inference
} // namespace paddle
+178
View File
@@ -0,0 +1,178 @@
/* Copyright (c) 2021 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <cmath>
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
static std::vector<float> truth_values = {
127.779f, 738.165f, 1013.22f, -438.17f, 366.401f, 927.659f, 736.222f,
-633.684f, -329.927f, -430.155f, -633.062f, -146.548f, -1324.28f, -1349.36f,
-242.675f, 117.448f, -801.723f, -391.514f, -404.818f, 454.16f, 515.48f,
-133.031f, 69.293f, 590.096f, -1434.69f, -1070.89f, 307.074f, 400.525f,
-316.12f, -587.125f, -161.056f, 800.363f, -96.4708f, 748.706f, 868.174f,
-447.938f, 112.737f, 1127.2f, 47.4355f, 677.72f, 593.186f, -336.4f,
551.362f, 397.823f, 78.3979f, -715.398f, 405.969f, 404.256f, 246.019f,
-8.42969f, 131.365f, -648.051f};
// Compare results with 1 batch
TEST(Analyzer_Resnet50_ipu, compare_results_1_batch) {
std::string model_dir = FLAGS_infer_model + "/" + "model";
AnalysisConfig config;
// ipu_device_num, ipu_micro_batch_size, ipu_enable_pipelining
config.EnableIpu(1, 1, false);
config.SetModel(model_dir + "/model", model_dir + "/params");
std::vector<PaddleTensor> inputs;
auto predictor = CreatePaddlePredictor(config);
const int batch = 1;
const int channel = 3;
const int height = 318;
const int width = 318;
const int input_num = batch * channel * height * width;
std::vector<float> input(input_num, 1);
PaddleTensor in;
in.shape = {batch, channel, height, width};
in.data =
PaddleBuf(static_cast<void*>(input.data()), input_num * sizeof(float));
in.dtype = PaddleDType::FLOAT32;
inputs.emplace_back(in);
std::vector<PaddleTensor> outputs;
ASSERT_TRUE(predictor->Run(inputs, &outputs));
const size_t expected_size = 1;
EXPECT_EQ(outputs.size(), expected_size);
float* data_o = static_cast<float*>(outputs[0].data.data());
for (size_t j = 0; j < outputs[0].data.length() / sizeof(float); j += 10) {
EXPECT_NEAR(
(data_o[j] - truth_values[j / 10]) / truth_values[j / 10], 0., 12e-5);
}
}
// Compare results with 2 batch
TEST(Analyzer_Resnet50_ipu, compare_results_2_batch) {
std::string model_dir = FLAGS_infer_model + "/" + "model";
AnalysisConfig config;
// ipu_device_num, ipu_micro_batch_size, ipu_enable_pipelining
config.EnableIpu(1, 2, false);
config.SetModel(model_dir + "/model", model_dir + "/params");
std::vector<PaddleTensor> inputs;
auto predictor = CreatePaddlePredictor(config);
const int batch = 2;
const int channel = 3;
const int height = 318;
const int width = 318;
const int input_num = batch * channel * height * width;
std::vector<float> input(input_num, 1);
PaddleTensor in;
in.shape = {batch, channel, height, width};
in.data =
PaddleBuf(static_cast<void*>(input.data()), input_num * sizeof(float));
in.dtype = PaddleDType::FLOAT32;
inputs.emplace_back(in);
std::vector<PaddleTensor> outputs;
ASSERT_TRUE(predictor->Run(inputs, &outputs));
const size_t expected_size = 1;
EXPECT_EQ(outputs.size(), expected_size);
float* data_o = static_cast<float*>(outputs[0].data.data());
auto num_output_per_batch = outputs[0].data.length() / sizeof(float) / 2;
for (size_t j = 0; j < num_output_per_batch; j += 10) {
EXPECT_NEAR(
(data_o[j] - truth_values[j / 10]) / truth_values[j / 10], 0., 12e-5);
EXPECT_NEAR((data_o[j + num_output_per_batch] - truth_values[j / 10]) /
truth_values[j / 10],
0.,
12e-5);
}
}
// multi threading
TEST(Analyzer_Resnet50_ipu, model_runtime_multi_thread) {
std::string model_dir = FLAGS_infer_model + "/" + "model";
AnalysisConfig config;
const int thread_num = 10;
// ipu_device_num, ipu_micro_batch_size, ipu_enable_pipelining
config.EnableIpu(1, 1, false);
config.SetIpuConfig(false, 1, 1.0, false, true);
config.SetModel(model_dir + "/model", model_dir + "/params");
auto main_predictor = CreatePaddlePredictor(config);
std::vector<std::vector<PaddleTensor>> inputs;
std::vector<std::vector<PaddleTensor>> outputs;
std::vector<decltype(main_predictor)> predictors;
std::vector<std::thread> threads;
outputs.resize(thread_num);
inputs.resize(thread_num);
const int batch = 1;
const int channel = 3;
const int height = 318;
const int width = 318;
const int input_num = batch * channel * height * width;
std::vector<float> input(input_num, 1);
PaddleTensor in;
in.shape = {batch, channel, height, width};
in.data =
PaddleBuf(static_cast<void*>(input.data()), input_num * sizeof(float));
in.dtype = PaddleDType::FLOAT32;
for (int i = 0; i < thread_num; ++i) {
inputs[i].emplace_back(in);
predictors.emplace_back(std::move(main_predictor->Clone()));
}
auto run = [](PaddlePredictor* predictor,
std::vector<PaddleTensor>& input,
std::vector<PaddleTensor>& output) {
ASSERT_TRUE(predictor->Run(input, &output));
};
for (int i = 0; i < thread_num; ++i) {
threads.emplace_back(
run, predictors[i].get(), std::ref(inputs[i]), std::ref(outputs[i]));
}
for (int i = 0; i < thread_num; ++i) {
threads[i].join();
}
const size_t expected_size = 1;
for (int i = 0; i < thread_num; ++i) {
EXPECT_EQ(outputs[i].size(), expected_size);
float* data_o = static_cast<float*>(outputs[i][0].data.data());
for (size_t j = 0; j < outputs[i][0].data.length() / sizeof(float);
j += 10) {
EXPECT_NEAR(
(data_o[j] - truth_values[j / 10]) / truth_values[j / 10], 0., 12e-5);
}
}
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,82 @@
/* Copyright (c) 2022 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 contains a simple demo for how to take a model for inference with
* IPUs.
* Model: wget -q
* http://paddle-inference-dist.bj.bcebos.com/word2vec.inference.model.tar.gz
*/
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
#include "glog/logging.h"
#include "paddle/common/flags.h"
#include "paddle/fluid/inference/api/paddle_inference_api.h"
PD_DEFINE_string(infer_model, "", "Directory of the inference model.");
using paddle_infer::Config;
using paddle_infer::CreatePredictor;
using paddle_infer::Predictor;
void inference(std::string model_path,
bool use_ipu,
std::vector<float> *out_data) {
//# 1. Create Predictor with a config.
Config config;
config.SetModel(FLAGS_infer_model);
if (use_ipu) {
// ipu_device_num, ipu_micro_batch_size
config.EnableIpu(1, 4);
}
auto predictor = CreatePredictor(config);
//# 2. Prepare input/output tensor.
auto input_names = predictor->GetInputNames();
std::vector<int64_t> data{1, 2, 3, 4};
// For simplicity, we set all the slots with the same data.
for (auto input_name : input_names) {
auto input_tensor = predictor->GetInputHandle(input_name);
input_tensor->Reshape({4, 1});
input_tensor->CopyFromCpu(data.data());
}
//# 3. Run
predictor->Run();
//# 4. Get output.
auto output_names = predictor->GetOutputNames();
auto output_tensor = predictor->GetOutputHandle(output_names[0]);
std::vector<int> output_shape = output_tensor->shape();
int out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
out_data->resize(out_num);
output_tensor->CopyToCpu(out_data->data());
}
int main(int argc, char *argv[]) {
::paddle::flags::ParseCommandLineFlags(&argc, &argv);
std::vector<float> ipu_result;
std::vector<float> cpu_result;
inference(FLAGS_infer_model, true, &ipu_result);
inference(FLAGS_infer_model, false, &cpu_result);
for (size_t i = 0; i < ipu_result.size(); i++) {
CHECK_NEAR(ipu_result[i], cpu_result[i], 1e-6);
}
LOG(INFO) << "Finished";
}
@@ -0,0 +1,126 @@
/* 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <cmath>
#include <mutex> // NOLINT
#include <thread> // NOLINT
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
int test_predictor(const AnalysisConfig& config_in,
Barrier* barrier = nullptr) {
static std::mutex mutex;
AnalysisConfig config{config_in};
std::unique_ptr<PaddlePredictor> predictor;
{
std::unique_lock<std::mutex> lock(mutex);
predictor = CreatePaddlePredictor(config);
}
if (barrier) {
barrier->Wait();
}
std::vector<PaddleTensor> inputs;
std::vector<float> input({1});
PaddleTensor in;
in.shape = {1, 1};
in.data = PaddleBuf(static_cast<void*>(input.data()), 1 * sizeof(float));
in.dtype = PaddleDType::FLOAT32;
inputs.emplace_back(in);
std::vector<PaddleTensor> outputs;
predictor->Run(inputs, &outputs);
const std::vector<float> truth_values = {-0.00621776f,
-0.00620937f,
0.00990623f,
-0.0039817f,
-0.00074315f,
0.61229795f,
-0.00491806f,
-0.00068755f,
0.18409646f,
0.30090684f};
const size_t expected_size = 1;
EXPECT_EQ(outputs.size(), expected_size);
float* data_o = static_cast<float*>(outputs[0].data.data());
for (size_t j = 0; j < outputs[0].data.length() / sizeof(float); ++j) {
EXPECT_LT(std::abs(data_o[j] - truth_values[j]), 10e-6);
}
return 0;
}
int test_predictor_zero_copy(const AnalysisConfig& config_in,
Barrier* barrier = nullptr) {
static std::mutex mutex;
AnalysisConfig config{config_in};
std::unique_ptr<PaddlePredictor> predictor;
{
std::unique_lock<std::mutex> lock(mutex);
predictor = CreatePaddlePredictor(config);
}
if (barrier) {
barrier->Wait();
}
std::vector<float> input({1});
auto in_tensor =
predictor->GetInputTensor(predictor->GetInputNames().front());
in_tensor->Reshape({1, 1});
in_tensor->copy_from_cpu(input.data());
predictor->ZeroCopyRun();
auto out_tensor =
predictor->GetOutputTensor(predictor->GetOutputNames().front());
std::vector<float> data_o(10);
out_tensor->copy_to_cpu(data_o.data());
const std::vector<float> truth_values = {-0.00621776f,
-0.00620937f,
0.00990623f,
-0.0039817f,
-0.00074315f,
0.61229795f,
-0.00491806f,
-0.00068755f,
0.18409646f,
0.30090684f};
const size_t expected_size = 1;
EXPECT_EQ(predictor->GetOutputNames().size(), expected_size);
for (size_t j = 0; j < truth_values.size(); ++j) {
EXPECT_LT(std::abs(data_o[j] - truth_values[j]), 10e-6);
}
return 0;
}
#ifdef PADDLE_WITH_XPU
TEST(AnalysisPredictor, native_xpu) {
AnalysisConfig config;
config.EnableXpu();
config.SetModel(FLAGS_infer_model + "/" + "mul_model");
test_predictor(config);
test_predictor_zero_copy(config);
}
#endif
} // namespace inference
} // namespace paddle
@@ -0,0 +1,81 @@
// Copyright (c) 2022 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <string>
#include <thread> // NOLINT
#include <vector>
#include "paddle/fluid/framework/ir/pass.h"
#include "paddle/fluid/framework/tensor.h"
#include "paddle/fluid/inference/api/helper.h"
#include "paddle/fluid/inference/api/onnxruntime_predictor.h"
#include "paddle/fluid/inference/api/paddle_api.h"
#include "paddle/fluid/inference/api/paddle_inference_api.h"
#include "paddle/fluid/inference/utils/io_utils.h"
#include "paddle/phi/backends/cpu/cpu_info.h"
#include "test/cpp/inference/api/tester_helper.h"
PD_DEFINE_string(dirname, "", "dirname to tests.");
namespace paddle {
TEST(ONNXRuntimePredictor, onnxruntime_on) {
AnalysisConfig config;
config.SetModel(FLAGS_dirname + "/inference.pdmodel",
FLAGS_dirname + "/inference.pdiparams");
config.EnableONNXRuntime();
config.EnableORTOptimization();
config.SetCpuMathLibraryNumThreads(2);
LOG(INFO) << config.Summary();
auto _predictor =
CreatePaddlePredictor<AnalysisConfig,
paddle::PaddleEngineKind::kONNXRuntime>(config);
ASSERT_TRUE(_predictor);
auto* predictor = static_cast<ONNXRuntimePredictor*>(_predictor.get());
ASSERT_TRUE(predictor);
ASSERT_TRUE(!predictor->Clone());
// Dummy Input Data
std::vector<int64_t> input_shape = {-1, 3, 224, 224};
std::vector<float> input_data(1 * 3 * 224 * 224, 1.0);
std::vector<float> out_data;
out_data.resize(1000);
// testing all interfaces
auto input_names = predictor->GetInputNames();
auto output_names = predictor->GetOutputNames();
auto get_input_shape = predictor->GetInputTensorShape();
ASSERT_EQ(input_names.size(), 1UL);
ASSERT_EQ(output_names.size(), 1UL);
ASSERT_EQ(input_names[0], "inputs");
ASSERT_EQ(output_names[0], "save_infer_model/scale_0.tmp_1");
ASSERT_EQ(get_input_shape["inputs"], input_shape);
auto input_tensor = predictor->GetInputTensor(input_names[0]);
input_tensor->Reshape({1, 3, 224, 224});
auto output_tensor = predictor->GetOutputTensor(output_names[0]);
input_tensor->CopyFromCpu(input_data.data());
ASSERT_TRUE(predictor->ZeroCopyRun());
output_tensor->CopyToCpu(out_data.data());
predictor->TryShrinkMemory();
}
} // namespace paddle
@@ -0,0 +1,560 @@
/* Copyright (c) 2021 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 <cuda_runtime.h>
#include <gtest/gtest.h>
#include <array>
#include <cstring>
#include <functional>
#include <numeric>
#include "glog/logging.h"
#include "paddle/common/flags.h"
#include "paddle/fluid/inference/api/paddle_infer_contrib.h"
#include "paddle/phi/common/float16.h"
#include "test/cpp/inference/api/trt_test_helper.h"
namespace paddle_infer {
class InferApiTesterUtils {
public:
static std::unique_ptr<Tensor> CreateInferTensorForTest(
const std::string &name, PlaceType place, void *p_scope) {
auto var = static_cast<paddle::framework::Scope *>(p_scope)->Var(name);
var->GetMutable<phi::DenseTensor>();
phi::DeviceContextPool &pool = phi::DeviceContextPool::Instance();
const auto &dev_ctxs = pool.device_contexts();
std::unique_ptr<Tensor> res(new Tensor(p_scope, &dev_ctxs));
res->input_or_output_ = true;
res->SetName(name);
res->SetPlace(place, 0 /*device id*/);
return res;
}
};
TEST(Tensor, copy_to_cpu_async_stream) {
LOG(INFO) << GetVersion();
UpdateDllFlag("conv_workspace_size_limit", "4000");
std::string model_dir = FLAGS_infer_model + "/model";
Config config;
config.EnableNewIR(false);
config.SetModel(model_dir + "/model", model_dir + "/params");
config.EnableUseGpu(100, 0);
auto predictor = CreatePredictor(config);
auto pred_clone = predictor->Clone();
std::vector<int> in_shape = {1, 3, 318, 318};
int in_num = std::accumulate(
in_shape.begin(), in_shape.end(), 1, std::multiplies<int>());
std::vector<float> input(in_num, 1.0);
const auto &input_names = predictor->GetInputNames();
auto input_tensor = predictor->GetInputHandle(input_names[0]);
input_tensor->Reshape(in_shape);
input_tensor->CopyFromCpu(input.data());
predictor->Run();
const auto &output_names = predictor->GetOutputNames();
auto output_tensor = predictor->GetOutputHandle(output_names[0]);
std::vector<int> output_shape = output_tensor->shape();
int out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
float *out_data = static_cast<float *>(
contrib::TensorUtils::CudaMallocPinnedMemory(sizeof(float) * out_num));
memset(out_data, 0, sizeof(float) * out_num);
std::vector<float> correct_out_data = {
127.78,
1.07353,
-229.42,
1127.28,
-177.365,
-292.412,
-271.614,
466.054,
540.436,
-214.223,
};
for (int i = 0; i < 100; i++) {
predictor->Run();
}
cudaStream_t stream;
output_tensor->CopyToCpuAsync(out_data, static_cast<void *>(&stream));
// sync
cudaStreamSynchronize(stream);
for (int i = 0; i < 10; i++) {
EXPECT_NEAR(out_data[i] / correct_out_data[i], 1.0, 1e-3);
}
contrib::TensorUtils::CudaFreePinnedMemory(static_cast<void *>(out_data));
}
TEST(Tensor, copy_to_cpu_async_callback) {
LOG(INFO) << GetVersion();
UpdateDllFlag("conv_workspace_size_limit", "4000");
std::string model_dir = FLAGS_infer_model + "/model";
Config config;
config.SwitchIrOptim(false);
config.EnableNewIR(false);
config.SetModel(model_dir + "/model", model_dir + "/params");
config.EnableUseGpu(100, 0);
auto predictor = CreatePredictor(config);
auto pred_clone = predictor->Clone();
std::vector<int> in_shape = {1, 3, 318, 318};
int in_num = std::accumulate(
in_shape.begin(), in_shape.end(), 1, std::multiplies<int>());
std::vector<float> input(in_num, 1.0);
const auto &input_names = predictor->GetInputNames();
auto input_tensor = predictor->GetInputHandle(input_names[0]);
input_tensor->Reshape(in_shape);
input_tensor->CopyFromCpu(input.data());
predictor->Run();
const auto &output_names = predictor->GetOutputNames();
auto output_tensor = predictor->GetOutputHandle(output_names[0]);
std::vector<int> output_shape = output_tensor->shape();
int out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
float *out_data = static_cast<float *>(
contrib::TensorUtils::CudaMallocPinnedMemory(sizeof(float) * out_num));
memset(out_data, 0, sizeof(float) * out_num);
for (int i = 0; i < 100; i++) {
predictor->Run();
}
cudaDeviceSynchronize();
output_tensor->CopyToCpuAsync(
out_data,
[](void *cb_params) {
float *data = static_cast<float *>(cb_params);
std::vector<float> correct_out_data = {
127.78,
1.07353,
-229.42,
1127.28,
-177.365,
-292.412,
-271.614,
466.054,
540.436,
-214.223,
};
for (int i = 0; i < 10; i++) {
EXPECT_NEAR(data[i] / correct_out_data[i], 1.0, 1e-3);
}
},
static_cast<void *>(out_data));
cudaDeviceSynchronize();
contrib::TensorUtils::CudaFreePinnedMemory(static_cast<void *>(out_data));
}
template <class DTYPE>
static void test_copy_tensor(PlaceType src_place, PlaceType dst_place) {
paddle::framework::Scope scope;
auto tensor_src = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_src", src_place, static_cast<void *>(&scope));
auto tensor_dst = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_dst", dst_place, static_cast<void *>(&scope));
std::vector<DTYPE> data_src(6, 1);
tensor_src->Reshape({2, 3});
tensor_src->CopyFromCpu(data_src.data());
std::vector<DTYPE> data_dst(4, 2);
tensor_dst->Reshape({2, 2});
tensor_dst->CopyFromCpu(data_dst.data());
paddle_infer::contrib::TensorUtils::CopyTensor(tensor_dst.get(), *tensor_src);
EXPECT_EQ(tensor_dst->shape().size(), (size_t)2);
EXPECT_EQ(tensor_dst->shape()[0], 2);
EXPECT_EQ(tensor_dst->shape()[1], 3);
std::vector<DTYPE> data_check(6, 3);
tensor_dst->CopyToCpu<DTYPE>(static_cast<DTYPE *>(data_check.data()));
for (int i = 0; i < 6; i++) {
EXPECT_NEAR(data_check[i], 1, 1e-5);
}
}
TEST(CopyTensor, float64) {
test_copy_tensor<double>(PlaceType::kCPU, PlaceType::kCPU);
test_copy_tensor<double>(PlaceType::kCPU, PlaceType::kGPU);
test_copy_tensor<double>(PlaceType::kGPU, PlaceType::kCPU);
test_copy_tensor<double>(PlaceType::kGPU, PlaceType::kGPU);
}
TEST(CopyTensor, float32) {
test_copy_tensor<float>(PlaceType::kCPU, PlaceType::kCPU);
test_copy_tensor<float>(PlaceType::kCPU, PlaceType::kGPU);
test_copy_tensor<float>(PlaceType::kGPU, PlaceType::kCPU);
test_copy_tensor<float>(PlaceType::kGPU, PlaceType::kGPU);
}
TEST(CopyTensor, int32) {
test_copy_tensor<int32_t>(PlaceType::kCPU, PlaceType::kCPU);
test_copy_tensor<int32_t>(PlaceType::kCPU, PlaceType::kGPU);
test_copy_tensor<int32_t>(PlaceType::kGPU, PlaceType::kCPU);
test_copy_tensor<int32_t>(PlaceType::kGPU, PlaceType::kGPU);
}
TEST(CopyTensor, int64) {
test_copy_tensor<int64_t>(PlaceType::kCPU, PlaceType::kCPU);
test_copy_tensor<int64_t>(PlaceType::kCPU, PlaceType::kGPU);
test_copy_tensor<int64_t>(PlaceType::kGPU, PlaceType::kCPU);
test_copy_tensor<int64_t>(PlaceType::kGPU, PlaceType::kGPU);
}
TEST(CopyTensor, int8) {
test_copy_tensor<int8_t>(PlaceType::kCPU, PlaceType::kCPU);
test_copy_tensor<int8_t>(PlaceType::kCPU, PlaceType::kGPU);
test_copy_tensor<int8_t>(PlaceType::kGPU, PlaceType::kCPU);
test_copy_tensor<int8_t>(PlaceType::kGPU, PlaceType::kGPU);
}
TEST(CopyTensor, uint8) {
test_copy_tensor<uint8_t>(PlaceType::kCPU, PlaceType::kCPU);
test_copy_tensor<uint8_t>(PlaceType::kCPU, PlaceType::kGPU);
test_copy_tensor<uint8_t>(PlaceType::kGPU, PlaceType::kCPU);
test_copy_tensor<uint8_t>(PlaceType::kGPU, PlaceType::kGPU);
}
TEST(CopyTensor, bool_cpu_to_cpu) {
paddle::framework::Scope scope;
auto tensor_src = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_src", PlaceType::kCPU, static_cast<void *>(&scope));
auto tensor_dst = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_dst", PlaceType::kCPU, static_cast<void *>(&scope));
std::array<bool, 6> data_src;
data_src.fill(true);
tensor_src->Reshape({2, 3});
tensor_src->CopyFromCpu(data_src.data());
std::array<bool, 4> data_dst;
data_dst.fill(false);
tensor_dst->Reshape({2, 2});
tensor_dst->CopyFromCpu(data_dst.data());
paddle_infer::contrib::TensorUtils::CopyTensor(tensor_dst.get(), *tensor_src);
EXPECT_EQ(tensor_dst->shape().size(), (size_t)2);
EXPECT_EQ(tensor_dst->shape()[0], 2);
EXPECT_EQ(tensor_dst->shape()[1], 3);
std::array<bool, 6> data_check;
data_check.fill(false);
tensor_dst->CopyToCpu<bool>(data_check.data());
for (int i = 0; i < 6; i++) {
EXPECT_TRUE(data_check[i] == true);
}
}
TEST(CopyTensor, bool_gpu_to_gpu) {
paddle::framework::Scope scope;
auto tensor_src = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_src", PlaceType::kGPU, static_cast<void *>(&scope));
auto tensor_dst = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_dst", PlaceType::kGPU, static_cast<void *>(&scope));
std::array<bool, 6> data_src;
data_src.fill(true);
tensor_src->Reshape({2, 3});
tensor_src->CopyFromCpu(data_src.data());
std::array<bool, 4> data_dst;
data_dst.fill(false);
tensor_dst->Reshape({2, 2});
tensor_dst->CopyFromCpu(data_dst.data());
paddle_infer::contrib::TensorUtils::CopyTensor(tensor_dst.get(), *tensor_src);
EXPECT_EQ(tensor_dst->shape().size(), (size_t)2);
EXPECT_EQ(tensor_dst->shape()[0], 2);
EXPECT_EQ(tensor_dst->shape()[1], 3);
std::array<bool, 6> data_check;
data_check.fill(false);
tensor_dst->CopyToCpu<bool>(data_check.data());
for (int i = 0; i < 6; i++) {
EXPECT_TRUE(data_check[i] == true);
}
}
TEST(CopyTensor, bool_gpu_to_cpu) {
paddle::framework::Scope scope;
auto tensor_src = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_src", PlaceType::kGPU, static_cast<void *>(&scope));
auto tensor_dst = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_dst", PlaceType::kCPU, static_cast<void *>(&scope));
std::array<bool, 6> data_src;
data_src.fill(true);
tensor_src->Reshape({2, 3});
tensor_src->CopyFromCpu(data_src.data());
std::array<bool, 4> data_dst;
data_dst.fill(false);
tensor_dst->Reshape({2, 2});
tensor_dst->CopyFromCpu(data_dst.data());
paddle_infer::contrib::TensorUtils::CopyTensor(tensor_dst.get(), *tensor_src);
EXPECT_EQ(tensor_dst->shape().size(), (size_t)2);
EXPECT_EQ(tensor_dst->shape()[0], 2);
EXPECT_EQ(tensor_dst->shape()[1], 3);
std::array<bool, 6> data_check;
data_check.fill(false);
tensor_dst->CopyToCpu<bool>(data_check.data());
for (int i = 0; i < 6; i++) {
EXPECT_TRUE(data_check[i] == true);
}
}
TEST(CopyTensor, bool_cpu_to_gpu) {
paddle::framework::Scope scope;
auto tensor_src = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_src", PlaceType::kCPU, static_cast<void *>(&scope));
auto tensor_dst = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_dst", PlaceType::kGPU, static_cast<void *>(&scope));
std::array<bool, 6> data_src;
data_src.fill(true);
tensor_src->Reshape({2, 3});
tensor_src->CopyFromCpu(data_src.data());
std::array<bool, 4> data_dst;
data_dst.fill(false);
tensor_dst->Reshape({2, 2});
tensor_dst->CopyFromCpu(data_dst.data());
paddle_infer::contrib::TensorUtils::CopyTensor(tensor_dst.get(), *tensor_src);
EXPECT_EQ(tensor_dst->shape().size(), (size_t)2);
EXPECT_EQ(tensor_dst->shape()[0], 2);
EXPECT_EQ(tensor_dst->shape()[1], 3);
std::array<bool, 6> data_check{false};
data_check.fill(false);
tensor_dst->CopyToCpu<bool>(data_check.data());
for (int i = 0; i < 6; i++) {
EXPECT_TRUE(data_check[i] == true);
}
}
TEST(CopyTensor, float16_cpu_to_cpu) {
paddle::framework::Scope scope;
auto tensor_src = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_src", PlaceType::kCPU, static_cast<void *>(&scope));
auto tensor_dst = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_dst", PlaceType::kCPU, static_cast<void *>(&scope));
using phi::dtype::float16;
std::vector<float16> data_src(6, float16(1.0));
tensor_src->Reshape({2, 3});
tensor_src->CopyFromCpu(data_src.data());
std::vector<float16> data_dst(4, float16(2.0));
tensor_dst->Reshape({2, 2});
tensor_dst->CopyFromCpu(data_dst.data());
paddle_infer::contrib::TensorUtils::CopyTensor(tensor_dst.get(), *tensor_src);
EXPECT_EQ(tensor_dst->shape().size(), (size_t)2);
EXPECT_EQ(tensor_dst->shape()[0], 2);
EXPECT_EQ(tensor_dst->shape()[1], 3);
std::vector<float16> data_check(6, float16(2.0));
tensor_dst->CopyToCpu<float16>(data_check.data());
for (int i = 0; i < 6; i++) {
EXPECT_TRUE(data_check[i] == float16(1.0));
}
}
TEST(CopyTensor, float16_gpu_to_gpu) {
paddle::framework::Scope scope;
auto tensor_src = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_src", PlaceType::kGPU, static_cast<void *>(&scope));
auto tensor_dst = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_dst", PlaceType::kGPU, static_cast<void *>(&scope));
using phi::dtype::float16;
std::vector<float16> data_src(6, float16(1.0));
tensor_src->Reshape({2, 3});
tensor_src->CopyFromCpu(data_src.data());
std::vector<float16> data_dst(4, float16(2.0));
tensor_dst->Reshape({2, 2});
tensor_dst->CopyFromCpu(data_dst.data());
paddle_infer::contrib::TensorUtils::CopyTensor(tensor_dst.get(), *tensor_src);
EXPECT_EQ(tensor_dst->shape().size(), (size_t)2);
EXPECT_EQ(tensor_dst->shape()[0], 2);
EXPECT_EQ(tensor_dst->shape()[1], 3);
std::vector<float16> data_check(6, float16(2.0));
tensor_dst->CopyToCpu<float16>(data_check.data());
for (int i = 0; i < 6; i++) {
EXPECT_TRUE(data_check[i] == float16(1.0));
}
}
TEST(CopyTensor, float16_cpu_to_gpu) {
paddle::framework::Scope scope;
auto tensor_src = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_src", PlaceType::kCPU, static_cast<void *>(&scope));
auto tensor_dst = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_dst", PlaceType::kGPU, static_cast<void *>(&scope));
using phi::dtype::float16;
std::vector<float16> data_src(6, float16(1.0));
tensor_src->Reshape({2, 3});
tensor_src->CopyFromCpu(data_src.data());
std::vector<float16> data_dst(4, float16(2.0));
tensor_dst->Reshape({2, 2});
tensor_dst->CopyFromCpu(data_dst.data());
paddle_infer::contrib::TensorUtils::CopyTensor(tensor_dst.get(), *tensor_src);
EXPECT_EQ(tensor_dst->shape().size(), (size_t)2);
EXPECT_EQ(tensor_dst->shape()[0], 2);
EXPECT_EQ(tensor_dst->shape()[1], 3);
std::vector<float16> data_check(6, float16(2.0));
tensor_dst->CopyToCpu<float16>(data_check.data());
for (int i = 0; i < 6; i++) {
EXPECT_TRUE(data_check[i] == float16(1.0));
}
}
TEST(CopyTensor, float16_gpu_to_cpu) {
paddle::framework::Scope scope;
auto tensor_src = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_src", PlaceType::kGPU, static_cast<void *>(&scope));
auto tensor_dst = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_dst", PlaceType::kCPU, static_cast<void *>(&scope));
using phi::dtype::float16;
std::vector<float16> data_src(6, float16(1.0));
tensor_src->Reshape({2, 3});
tensor_src->CopyFromCpu(data_src.data());
std::vector<float16> data_dst(4, float16(2.0));
tensor_dst->Reshape({2, 2});
tensor_dst->CopyFromCpu(data_dst.data());
paddle_infer::contrib::TensorUtils::CopyTensor(tensor_dst.get(), *tensor_src);
EXPECT_EQ(tensor_dst->shape().size(), (size_t)2);
EXPECT_EQ(tensor_dst->shape()[0], 2);
EXPECT_EQ(tensor_dst->shape()[1], 3);
std::vector<float16> data_check(6, float16(2.0));
tensor_dst->CopyToCpu<float16>(data_check.data());
for (int i = 0; i < 6; i++) {
EXPECT_TRUE(data_check[i] == float16(1.0));
}
}
TEST(CopyTensor, async_stream) {
paddle::framework::Scope scope;
auto tensor_src = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_src", PlaceType::kGPU, static_cast<void *>(&scope));
auto tensor_dst = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_dst", PlaceType::kGPU, static_cast<void *>(&scope));
std::vector<float> data_src(6, 1.0);
tensor_src->Reshape({2, 3});
tensor_src->CopyFromCpu(data_src.data());
std::vector<float> data_dst(4, 2.0);
tensor_dst->Reshape({2, 2});
tensor_dst->CopyFromCpu(data_dst.data());
cudaStream_t stream;
paddle_infer::contrib::TensorUtils::CopyTensorAsync(
tensor_dst.get(), *tensor_src, static_cast<void *>(&stream));
EXPECT_EQ(tensor_dst->shape().size(), (size_t)2);
EXPECT_EQ(tensor_dst->shape()[0], 2);
EXPECT_EQ(tensor_dst->shape()[1], 3);
cudaStreamSynchronize(stream);
std::vector<float> data_check(6, 1.0);
tensor_dst->CopyToCpu<float>(data_check.data());
for (int i = 0; i < 6; i++) {
EXPECT_NEAR(data_check[i], static_cast<float>(1.0), 1e-5);
}
}
TEST(CopyTensor, async_callback) {
paddle::framework::Scope scope;
auto tensor_src = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_src", PlaceType::kCPU, static_cast<void *>(&scope));
auto tensor_dst = paddle_infer::InferApiTesterUtils::CreateInferTensorForTest(
"tensor_dst", PlaceType::kGPU, static_cast<void *>(&scope));
std::vector<float> data_src(6, 1.0);
tensor_src->Reshape({2, 3});
tensor_src->CopyFromCpu(data_src.data());
std::vector<float> data_dst(4, 2.0);
tensor_dst->Reshape({2, 2});
tensor_dst->CopyFromCpu(data_dst.data());
paddle_infer::contrib::TensorUtils::CopyTensorAsync(
tensor_dst.get(),
*tensor_src,
[](void *cb_params) {
Tensor *tensor = static_cast<Tensor *>(cb_params);
EXPECT_EQ(tensor->shape().size(), (size_t)2);
EXPECT_EQ(tensor->shape()[0], 2);
EXPECT_EQ(tensor->shape()[1], 3);
},
static_cast<void *>(&(*tensor_dst)));
cudaDeviceSynchronize();
}
} // namespace paddle_infer
@@ -0,0 +1,90 @@
// Copyright (c) 2021 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 "glog/logging.h"
#include "gtest/gtest.h"
#include "paddle/common/flags.h"
#include "paddle/fluid/inference/api/paddle_infer_contrib.h"
#include "paddle/fluid/platform/enforce.h"
namespace paddle_infer {
namespace contrib {
TEST(Status, ctor) { CHECK(Status::OK().ok()); }
struct FakeException {
void pd_exception(int a) const {
PADDLE_ENFORCE_NE(a,
a,
common::errors::InvalidArgument(
"This is a preset error message used to verify "
"whether the exception meets expectations: %d, %d.",
a,
a));
}
[[noreturn]] void base_exception() const { throw std::exception(); }
void no_exception() const noexcept {}
};
TEST(Status, pd_exception) {
FakeException e;
Status status = get_status([&]() { e.pd_exception(1); });
PADDLE_ENFORCE_EQ(
status.ok(),
false,
common::errors::PreconditionNotMet("Status should not be OK."));
PADDLE_ENFORCE_EQ(
status == status,
true,
common::errors::PreconditionNotMet("Status should be equal to itself."));
PADDLE_ENFORCE_EQ(status != status,
false,
common::errors::PreconditionNotMet(
"Status should not be different from itself."));
PADDLE_ENFORCE_EQ(
status.code(),
common::ErrorCode::INVALID_ARGUMENT + 1,
common::errors::InvalidArgument(
"Required status.code() should be equal to INVALID_ARGUMENT + 1. "));
LOG(INFO) << status.error_message();
}
TEST(Status, basic_exception) {
FakeException e;
Status status;
status = get_status([&]() { e.base_exception(); });
PADDLE_ENFORCE_EQ(
status.ok(),
false,
common::errors::PreconditionNotMet("Status should not be OK."));
LOG(INFO) << status.error_message();
}
TEST(Status, no_exception) {
FakeException e;
Status status;
status = get_status([&]() { e.no_exception(); });
PADDLE_ENFORCE_EQ(status.ok(),
true,
common::errors::PreconditionNotMet("Status should be OK."));
}
TEST(Status, copy) {
Status status;
Status status_1(status);
status_1 = status;
}
} // namespace contrib
} // namespace paddle_infer
@@ -0,0 +1,97 @@
/* Copyright (c) 2022 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <functional>
#include <numeric>
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle_infer {
TEST(Predictor, use_gpu) {
LOG(INFO) << GetVersion();
UpdateDllFlag("conv_workspace_size_limit", "4000");
std::string model_dir = FLAGS_infer_model + "/model";
Config config;
config.EnableNewIR(false);
config.SetModel(model_dir + "/model", model_dir + "/params");
config.EnableUseGpu(100, 0);
auto predictor = CreatePredictor(config);
auto pred_clone = predictor->Clone();
std::vector<int> in_shape = {1, 3, 318, 318};
int in_num = std::accumulate(
in_shape.begin(), in_shape.end(), 1, std::multiplies<int>());
std::vector<float> input(in_num, 0);
auto input_names = predictor->GetInputNames();
auto input_t = predictor->GetInputHandle(input_names[0]);
input_t->Reshape(in_shape);
input_t->CopyFromCpu(input.data());
predictor->Run();
auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputHandle(output_names[0]);
std::vector<int> output_shape = output_t->shape();
int out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
std::vector<float> out_data;
out_data.resize(out_num);
output_t->CopyToCpu(out_data.data());
predictor->ClearIntermediateTensor();
}
TEST(PredictorPool, basic) {
LOG(INFO) << GetVersion();
UpdateDllFlag("conv_workspace_size_limit", "4000");
std::string model_dir = FLAGS_infer_model + "/model";
Config config;
config.EnableNewIR(false);
config.SetModel(model_dir + "/model", model_dir + "/params");
config.EnableUseGpu(100, 0);
services::PredictorPool pred_pool(config, 4);
auto pred = pred_pool.Retrieve(2);
std::vector<int> in_shape = {1, 3, 318, 318};
int in_num = std::accumulate(
in_shape.begin(), in_shape.end(), 1, std::multiplies<int>());
std::vector<float> input(in_num, 0);
auto in_names = pred->GetInputNames();
auto input_t = pred->GetInputHandle(in_names[0]);
input_t->name();
input_t->Reshape(in_shape);
input_t->CopyFromCpu(input.data());
pred->Run();
auto out_names = pred->GetOutputNames();
auto output_t = pred->GetOutputHandle(out_names[0]);
auto out_type = output_t->type();
LOG(INFO) << GetNumBytesOfDataType(out_type);
if (out_type == DataType::FLOAT32) {
PlaceType place;
int size;
output_t->data<float>(&place, &size);
}
}
} // namespace paddle_infer
@@ -0,0 +1,30 @@
# 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.
import os
import unittest
class Test_Preprocess(unittest.TestCase):
def test_local_convert(self):
os.system("python full_pascalvoc_test_preprocess.py --choice=local")
def test_online_convert(self):
os.system(
"python full_pascalvoc_test_preprocess.py --choice=VOC_test_2007"
)
if __name__ == '__main__':
unittest.main()
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,62 @@
/* 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. */
#include <glog/logging.h>
#include <gtest/gtest.h>
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/trt_test_helper.h"
namespace paddle {
namespace inference {
TEST(TensorRT, cascade_rcnn) {
std::string model_dir = FLAGS_infer_model + "/cascade_rcnn";
AnalysisConfig config;
int batch_size = 1;
config.EnableNewIR(false);
config.EnableUseGpu(100, 0);
config.SetModel(model_dir + "/model", model_dir + "/params");
config.EnableTensorRtEngine(
1 << 30, batch_size, 40, AnalysisConfig::Precision::kFloat32, false);
auto predictor = CreatePaddlePredictor(config);
int channels = 3;
int height = 640;
int width = 640;
int input_num = batch_size * channels * height * width;
float *input = new float[input_num];
memset(input, 1.0, input_num * sizeof(float));
float *im_shape = new float[3];
im_shape[0] = 3.0;
im_shape[1] = 640.0;
im_shape[2] = 640.0;
auto input_names = predictor->GetInputNames();
auto input_t = predictor->GetInputTensor(input_names[0]);
input_t->Reshape({batch_size, channels, height, width});
input_t->copy_from_cpu(input);
auto input_t1 = predictor->GetInputTensor(input_names[1]);
input_t1->Reshape({batch_size, 3});
input_t1->copy_from_cpu(im_shape);
ASSERT_TRUE(predictor->ZeroCopyRun());
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,43 @@
/* Copyright (c) 2023 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 <glog/logging.h>
#include <gtest/gtest.h>
#include "test/cpp/inference/api/trt_test_helper.h"
namespace paddle {
namespace inference {
TEST(TensorRT, disable_tensorrt_half_ops) {
std::string model_dir = FLAGS_infer_model + "/resnet50";
AnalysisConfig config;
config.SetModel(model_dir);
config.EnableUseGpu(100, 0);
config.EnableTensorRtEngine(
1 << 30, 1, 5, AnalysisConfig::Precision::kHalf, false, false);
paddle_infer::experimental::InternalUtils::DisableTensorRtHalfOps(&config,
{"conv2d"});
std::vector<std::vector<PaddleTensor>> inputs_all;
auto predictor = CreatePaddlePredictor(config);
SetFakeImageInput(&inputs_all, model_dir, false, "__model__", "");
std::vector<PaddleTensor> outputs;
for (auto &input : inputs_all) {
ASSERT_TRUE(predictor->Run(input, &outputs));
predictor->ClearIntermediateTensor();
}
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,38 @@
/* 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 <dirent.h>
#ifndef _WIN32
#include <unistd.h>
#else // headers below are substitute of unistd.h in windows
#include <io.h>
#include <process.h>
#endif
#include <glog/logging.h>
#include <gtest/gtest.h>
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/trt_dynamic_shape_ernie_serialize_deserialize_test.h"
namespace paddle {
namespace inference {
TEST(AnalysisPredictor, fp16) {
std::vector<float> result = {0.59923654, 0.21923761, 0.18152587};
trt_ernie(true, result);
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,40 @@
/* 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 <dirent.h>
#ifndef _WIN32
#include <unistd.h>
#else // headers below are substitute of unistd.h in windows
#include <io.h>
#include <process.h>
#endif
#include <glog/logging.h>
#include <gtest/gtest.h>
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/trt_dynamic_shape_ernie_serialize_deserialize_test.h"
namespace paddle {
namespace inference {
#if defined _WIN32
#else
TEST(AnalysisPredictor, no_fp16) {
std::vector<float> result = {0.597841, 0.219972, 0.182187};
trt_ernie(false, result);
}
#endif
} // namespace inference
} // namespace paddle
@@ -0,0 +1,153 @@
/* 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. */
#pragma once
#include <glog/logging.h>
#include <gtest/gtest.h>
#ifndef _WIN32
#include <unistd.h>
#else // headers below are substitute of unistd.h in windows
#include <io.h>
#include <process.h>
#endif
#include <functional>
#include <map>
#include <string>
#include <vector>
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/trt_test_helper.h"
namespace paddle {
namespace inference {
static void run(const AnalysisConfig& config, std::vector<float>* out_data) {
auto predictor = CreatePaddlePredictor(config);
auto input_names = predictor->GetInputNames();
int run_batch = 1;
const int run_seq_len = 128;
std::vector<int32_t> tmp_input;
std::vector<float> tmp_four_input;
tmp_input.reserve(run_batch * run_seq_len);
tmp_four_input.reserve(run_batch * run_seq_len);
int32_t i0[run_seq_len] = {
1, 3558, 4, 75, 491, 89, 340, 313, 93, 4, 255, 10, 75, 321,
4095, 1902, 4, 134, 49, 75, 311, 14, 44, 178, 543, 15, 12043, 2,
75, 201, 340, 9, 14, 44, 486, 218, 1140, 279, 12043, 2};
int32_t i1[run_seq_len] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int32_t i2[run_seq_len] = {0, 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, 36, 37, 38, 39};
float i3[run_seq_len] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
// first input
auto input_t = predictor->GetInputTensor(input_names[0]);
input_t->Reshape({run_batch, run_seq_len, 1});
input_t->copy_from_cpu(i0);
// second input
auto input_t2 = predictor->GetInputTensor(input_names[1]);
input_t2->Reshape({run_batch, run_seq_len, 1});
input_t2->copy_from_cpu(i1);
// third input.
auto input_t3 = predictor->GetInputTensor(input_names[2]);
input_t3->Reshape({run_batch, run_seq_len, 1});
input_t3->copy_from_cpu(i2);
auto input_t4 = predictor->GetInputTensor(input_names[3]);
input_t4->Reshape({run_batch, run_seq_len, 1});
input_t4->copy_from_cpu(i3);
ASSERT_TRUE(predictor->ZeroCopyRun());
auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputTensor(output_names[0]);
std::vector<int> output_shape = output_t->shape();
int out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
out_data->resize(out_num);
output_t->copy_to_cpu(out_data->data());
}
static void trt_ernie(bool with_fp16, std::vector<float> result) {
AnalysisConfig config;
std::string model_dir = FLAGS_infer_model;
// Delete serialization cache to perform serialization first rather than
// deserialization.
std::string opt_cache_dir = FLAGS_infer_model + "/opt_cache";
delete_cache_files(opt_cache_dir);
config.SetOptimCacheDir(opt_cache_dir);
SetConfig(&config, model_dir, true /* use_gpu */);
int batch = 1;
int min_seq_len = 1;
int max_seq_len = 128;
int opt_seq_len = 128;
std::vector<int> min_shape = {batch, min_seq_len, 1};
std::vector<int> max_shape = {batch, max_seq_len, 1};
std::vector<int> opt_shape = {batch, opt_seq_len, 1};
// Set the input's min, max, opt shape
std::map<std::string, std::vector<int>> min_input_shape = {
{"read_file_0.tmp_0", min_shape},
{"read_file_0.tmp_1", min_shape},
{"read_file_0.tmp_2", min_shape},
{"read_file_0.tmp_4", min_shape}};
std::map<std::string, std::vector<int>> max_input_shape = {
{"read_file_0.tmp_0", max_shape},
{"read_file_0.tmp_1", max_shape},
{"read_file_0.tmp_2", max_shape},
{"read_file_0.tmp_4", max_shape}};
std::map<std::string, std::vector<int>> opt_input_shape = {
{"read_file_0.tmp_0", opt_shape},
{"read_file_0.tmp_1", opt_shape},
{"read_file_0.tmp_2", opt_shape},
{"read_file_0.tmp_4", opt_shape}};
auto precision = AnalysisConfig::Precision::kFloat32;
if (with_fp16) {
precision = AnalysisConfig::Precision::kHalf;
}
config.EnableTensorRtEngine(1 << 30, 1, 5, precision, true, false);
config.SetTRTDynamicShapeInfo(
min_input_shape, max_input_shape, opt_input_shape);
paddle_infer::experimental::InternalUtils::SetTransformerMaskid(
&config, "read_file_0.tmp_4");
AnalysisConfig* config_deser = new AnalysisConfig(config);
std::vector<float> out_data;
run(config, &out_data); // serialize
run(*config_deser, &out_data); // deserialize
for (size_t i = 0; i < out_data.size(); i++) {
EXPECT_NEAR(result[i], out_data[i], 1e-2);
}
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,443 @@
/* 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 <glog/logging.h>
#include <gtest/gtest.h>
#include "paddle/common/flags.h"
#include "paddle/common/enforce.h"
#include "paddle/fluid/inference/tensorrt/helper.h"
#include "test/cpp/inference/api/trt_test_helper.h"
namespace paddle {
namespace inference {
void run(const AnalysisConfig& config, std::vector<float>* out_data, int bs) {
#if !defined(_WIN32)
setenv("NVIDIA_TF32_OVERRIDE", "0", 1);
#endif
auto predictor = CreatePaddlePredictor(config);
auto input_names = predictor->GetInputNames();
int run_batch = bs;
const int run_seq_len = 128;
size_t len = run_batch * run_seq_len;
std::array<int32_t, 128> i0_bs1 = {
1, 3558, 4, 75, 491, 89, 340, 313, 93, 4, 255, 10, 75, 321,
4095, 1902, 4, 134, 49, 75, 311, 14, 44, 178, 543, 15, 12043, 2,
75, 201, 340, 9, 14, 44, 486, 218, 1140, 279, 12043, 2};
std::array<int32_t, 128> i1_bs1 = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
std::array<int32_t, 128> i2_bs1 = {0, 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, 36, 37, 38, 39};
std::array<float, 128> i3_bs1 = {
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
std::vector<int32_t> i0_data(len), i1_data(len), i2_data(len);
std::vector<float> i3_data(len);
for (size_t i = 0; i < len; i++) {
i0_data[i] = i0_bs1[i % run_seq_len];
i1_data[i] = i1_bs1[i % run_seq_len];
i2_data[i] = i2_bs1[i % run_seq_len];
i3_data[i] = i3_bs1[i % run_seq_len];
}
// first input
auto input_t = predictor->GetInputTensor(input_names[0]);
input_t->Reshape({run_batch, run_seq_len, 1});
input_t->copy_from_cpu(i0_data.data());
// second input
auto input_t2 = predictor->GetInputTensor(input_names[1]);
input_t2->Reshape({run_batch, run_seq_len, 1});
input_t2->copy_from_cpu(i1_data.data());
// third input.
auto input_t3 = predictor->GetInputTensor(input_names[2]);
input_t3->Reshape({run_batch, run_seq_len, 1});
input_t3->copy_from_cpu(i2_data.data());
auto input_t4 = predictor->GetInputTensor(input_names[3]);
input_t4->Reshape({run_batch, run_seq_len, 1});
input_t4->copy_from_cpu(i3_data.data());
ASSERT_TRUE(predictor->ZeroCopyRun());
auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputTensor(output_names[0]);
std::vector<int> output_shape = output_t->shape();
int out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
out_data->resize(out_num);
output_t->copy_to_cpu(out_data->data());
}
void trt_ernie(bool with_fp16,
std::vector<float> result,
float near_tolerance,
int batch_size = 1) {
AnalysisConfig config;
std::string model_dir = FLAGS_infer_model;
SetConfig(&config, model_dir, true);
int batch = 32;
int min_seq_len = 1;
int max_seq_len = 128;
int opt_seq_len = 128;
std::vector<int> min_shape = {1, min_seq_len, 1};
std::vector<int> max_shape = {batch, max_seq_len, 1};
std::vector<int> opt_shape = {batch, opt_seq_len, 1};
// Set the input's min, max, opt shape
std::map<std::string, std::vector<int>> min_input_shape = {
{"read_file_0.tmp_0", min_shape},
{"read_file_0.tmp_1", min_shape},
{"read_file_0.tmp_2", min_shape},
{"read_file_0.tmp_4", min_shape}};
std::map<std::string, std::vector<int>> max_input_shape = {
{"read_file_0.tmp_0", max_shape},
{"read_file_0.tmp_1", max_shape},
{"read_file_0.tmp_2", max_shape},
{"read_file_0.tmp_4", max_shape}};
std::map<std::string, std::vector<int>> opt_input_shape = {
{"read_file_0.tmp_0", opt_shape},
{"read_file_0.tmp_1", opt_shape},
{"read_file_0.tmp_2", opt_shape},
{"read_file_0.tmp_4", opt_shape}};
auto precision = AnalysisConfig::Precision::kFloat32;
if (with_fp16) {
precision = AnalysisConfig::Precision::kHalf;
}
config.EnableTensorRtEngine(1 << 30, 1, 5, precision, false, false);
config.SetTRTDynamicShapeInfo(
min_input_shape, max_input_shape, opt_input_shape);
paddle_infer::experimental::InternalUtils::SetTransformerMaskid(
&config, "read_file_0.tmp_4");
std::vector<float> out_data;
run(config, &out_data, batch_size);
for (size_t i = 0; i < out_data.size(); i++) {
EXPECT_NEAR(result[i], out_data[i], near_tolerance);
}
}
TEST(AnalysisPredictor, no_fp16) {
std::vector<float> result = {0.597841, 0.219972, 0.182187};
trt_ernie(false, result, 1e-4);
}
TEST(AnalysisPredictor, fp16) {
#ifdef PADDLE_WITH_CUDA
std::vector<float> result = {0.598, 0.219, 0.182};
trt_ernie(true, result, 4e-3);
#endif
}
TEST(AnalysisPredictor, no_fp16_bs2) {
std::vector<float> result = {
0.597841, 0.219972, 0.182187, 0.597841, 0.219972, 0.182187};
trt_ernie(false, result, 1e-4, 2);
}
TEST(AnalysisPredictor, fp16_bs2) {
#ifdef PADDLE_WITH_CUDA
std::vector<float> result = {0.598, 0.219, 0.182, 0.598, 0.219, 0.182};
trt_ernie(true, result, 4e-3, 2);
#endif
}
// ernie_varlen
std::shared_ptr<paddle_infer::Predictor> InitPredictor() {
paddle_infer::Config config;
config.SetModel(FLAGS_infer_model);
config.EnableUseGpu(100, 0);
// Open the memory optim.
config.EnableMemoryOptim();
int max_batch = 32;
int max_single_seq_len = 128;
int opt_single_seq_len = 64;
int min_batch_seq_len = 1;
int max_batch_seq_len = 512;
int opt_batch_seq_len = 256;
std::string input_name0 = "read_file_0.tmp_0";
std::string input_name1 = "read_file_0.tmp_1";
std::string input_name2 = "read_file_0.tmp_2";
std::string input_name3 = "read_file_0.tmp_4";
std::vector<int> min_shape = {min_batch_seq_len};
std::vector<int> max_shape = {max_batch_seq_len};
std::vector<int> opt_shape = {opt_batch_seq_len};
// Set the input's min, max, opt shape
std::map<std::string, std::vector<int>> min_input_shape = {
{input_name0, min_shape},
{input_name1, min_shape},
{input_name2, {1}},
{input_name3, {1, 1, 1}}};
std::map<std::string, std::vector<int>> max_input_shape = {
{input_name0, max_shape},
{input_name1, max_shape},
{input_name2, {max_batch + 1}},
{input_name3, {1, max_single_seq_len, 1}}};
std::map<std::string, std::vector<int>> opt_input_shape = {
{input_name0, opt_shape},
{input_name1, opt_shape},
{input_name2, {max_batch + 1}},
{input_name3, {1, opt_single_seq_len, 1}}};
// only kHalf supported
config.EnableTensorRtEngine(
1 << 30, 1, 5, paddle_infer::Config::Precision::kHalf, false, false);
// erinie varlen must be used with dynamic shape
config.SetTRTDynamicShapeInfo(
min_input_shape, max_input_shape, opt_input_shape);
// erinie varlen must be used with oss
config.EnableVarseqlen();
paddle_infer::experimental::InternalUtils::SetTransformerPosid(&config,
input_name2);
paddle_infer::experimental::InternalUtils::SetTransformerMaskid(&config,
input_name3);
return paddle_infer::CreatePredictor(config);
}
void run(paddle_infer::Predictor* predictor, std::vector<float>* out_data) {
#if !defined(_WIN32)
setenv("NVIDIA_TF32_OVERRIDE", "0", 1);
#endif
const int run_batch = 2;
const int run_seq_len = 71;
const int max_seq_len = 128;
std::vector<int32_t> i1 = {
// sentence 1
1,
3558,
4,
75,
491,
89,
340,
313,
93,
4,
255,
10,
75,
321,
4095,
1902,
4,
134,
49,
75,
311,
14,
44,
178,
543,
15,
12043,
2,
75,
201,
340,
9,
14,
44,
486,
218,
1140,
279,
12043,
2,
// sentence 2
101,
2054,
2234,
2046,
2486,
2044,
1996,
2047,
4552,
2001,
9536,
1029,
102,
2004,
1997,
2008,
2154,
1010,
1996,
2047,
4552,
9536,
2075,
1996,
2117,
3072,
2234,
2046,
2486,
1012,
102,
};
std::vector<int32_t> i2 = {// sentence 1
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
// sentence 2
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1};
// shape info of this batch
std::vector<int32_t> i3 = {0, 40, 71};
// max_seq_len represents the max sentence length of all the sentences, only
// length of
// input i4 is useful, data means nothing.
std::vector<float> i4(max_seq_len, 0);
auto input_names = predictor->GetInputNames();
// first input
auto input_t1 = predictor->GetInputHandle(input_names[0]);
input_t1->Reshape({run_seq_len});
input_t1->CopyFromCpu(i1.data());
// second input
auto input_t2 = predictor->GetInputHandle(input_names[1]);
input_t2->Reshape({run_seq_len});
input_t2->CopyFromCpu(i2.data());
// third input
auto input_t3 = predictor->GetInputHandle(input_names[2]);
input_t3->Reshape({run_batch + 1});
input_t3->CopyFromCpu(i3.data());
// fourth input
auto input_t4 = predictor->GetInputHandle(input_names[3]);
input_t4->Reshape({1, max_seq_len, 1});
input_t4->CopyFromCpu(i4.data());
PADDLE_ENFORCE(
predictor->Run(),
common::errors::PreconditionNotMet("Predictor is not runnable"));
auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputHandle(output_names[0]);
std::vector<int> output_shape = output_t->shape();
int out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
out_data->resize(out_num);
output_t->CopyToCpu(out_data->data());
return;
}
TEST(AnalysisPredictor, ernie_varlen) {
#if IS_TRT_VERSION_GE(7234)
if (platform::GetGPUComputeCapability(platform::GetCurrentDeviceId()) >= 75) {
auto predictor = InitPredictor();
std::vector<float> out_data;
run(predictor.get(), &out_data);
std::vector<float> ref_data{
0.59814, 0.219882, 0.181978, 0.359796, 0.577414, 0.0627908};
float near_tolerance = 4e-3;
for (size_t i = 0; i < out_data.size(); i++) {
EXPECT_NEAR(ref_data[i], out_data[i], near_tolerance);
}
}
#endif
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,307 @@
/* 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 <glog/logging.h>
#include <gtest/gtest.h>
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/trt_test_helper.h"
namespace paddle {
namespace inference {
void TestDynamic(bool with_dynamic = true,
bool delete_cache = true,
bool delete_conv_bn = false) {
std::string model_dir =
FLAGS_infer_model + "/conv_bn_swish_split_gelu/conv_bn_swish_split_gelu";
std::string opt_cache_dir = model_dir + "/my_cache";
if (delete_cache) {
delete_cache_files(opt_cache_dir);
}
AnalysisConfig config;
config.EnableNewIR(false);
config.EnableUseGpu(100, 0);
std::string buffer_prog, buffer_param;
ReadBinaryFile(model_dir + "/model", &buffer_prog);
ReadBinaryFile(model_dir + "/params", &buffer_param);
config.SetModelBuffer(&buffer_prog[0],
buffer_prog.size(),
&buffer_param[0],
buffer_param.size());
config.SetOptimCacheDir(opt_cache_dir);
// Set the input's min, max, opt shape
config.EnableTensorRtEngine(
1 << 30, 1, 1, AnalysisConfig::Precision::kFloat32, true, true);
if (delete_conv_bn) {
config.pass_builder()->DeletePass("conv_bn_fuse_pass");
}
if (with_dynamic) {
std::map<std::string, std::vector<int>> min_input_shape = {
{"image", {1, 1, 3, 3}}};
std::map<std::string, std::vector<int>> max_input_shape = {
{"image", {1, 1, 10, 10}}};
std::map<std::string, std::vector<int>> opt_input_shape = {
{"image", {1, 1, 3, 3}}};
config.SetTRTDynamicShapeInfo(
min_input_shape, max_input_shape, opt_input_shape);
}
auto predictor = CreatePaddlePredictor(config);
auto input_names = predictor->GetInputNames();
int channels = 1;
int height = 3;
int width = 3;
int input_num = channels * height * width * 1;
float *input = new float[input_num];
memset(input, 0, input_num * sizeof(float));
auto input_t = predictor->GetInputTensor(input_names[0]);
input_t->Reshape({1, channels, height, width});
input_t->copy_from_cpu(input);
ASSERT_TRUE(predictor->ZeroCopyRun());
std::vector<float> out_data;
auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputTensor(output_names[0]);
std::vector<int> output_shape = output_t->shape();
int out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
out_data.resize(out_num);
output_t->copy_to_cpu(out_data.data());
}
void TestDynamic2() {
std::string model_dir =
FLAGS_infer_model + "/complex_model_dynamic/complex_model_dynamic2";
AnalysisConfig config;
config.EnableUseGpu(100, 0);
config.SetModel(model_dir + "/model", model_dir + "/params");
// Set the input's min, max, opt shape
int batch_size = 1;
std::map<std::string, std::vector<int>> min_input_shape = {
{"image", {1, 3, 3, 3}}, {"in1", {1, 2, 1, 1}}, {"in2", {1, 2, 1, 1}}};
std::map<std::string, std::vector<int>> max_input_shape = {
{"image", {1, 3, 10, 10}}, {"in1", {1, 2, 1, 1}}, {"in2", {1, 2, 1, 1}}};
std::map<std::string, std::vector<int>> opt_input_shape = {
{"image", {1, 3, 5, 5}}, {"in1", {1, 2, 1, 1}}, {"in2", {1, 2, 1, 1}}};
config.EnableTensorRtEngine(
1 << 30, batch_size, 0, AnalysisConfig::Precision::kFloat32, false, true);
config.SetTRTDynamicShapeInfo(
min_input_shape, max_input_shape, opt_input_shape);
auto predictor = CreatePaddlePredictor(config);
int channels = 3;
int height = 5;
int width = 5;
int input_num = channels * height * width * 1;
float *input = new float[input_num];
memset(input, 0, input_num * sizeof(float));
auto input_names = predictor->GetInputNames();
auto input_t = predictor->GetInputTensor(input_names[0]);
input_t->Reshape({batch_size, channels, height, width});
input_t->copy_from_cpu(input);
auto input_t1 = predictor->GetInputTensor(input_names[1]);
input_t1->Reshape({batch_size, 2, 1, 1});
std::vector<float> first;
for (int i = 0; i < batch_size * 2; i++) first.push_back(1.0);
input_t1->copy_from_cpu(first.data());
auto input_t2 = predictor->GetInputTensor(input_names[2]);
input_t2->Reshape({batch_size, 2, 1, 1});
input_t2->copy_from_cpu(first.data());
ASSERT_TRUE(predictor->ZeroCopyRun());
std::vector<float> out_data;
auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputTensor(output_names[0]);
std::vector<int> output_shape = output_t->shape();
int out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
out_data.resize(out_num);
output_t->copy_to_cpu(out_data.data());
std::vector<float> result = {0.617728, 1.63504, 2.15771, 0.535556};
for (size_t i = 0; i < out_data.size(); i++) {
EXPECT_NEAR(result[i], out_data[i], 1e-5);
}
}
void TestTunedDynamic() {
std::string model_dir =
FLAGS_infer_model + "/complex_model_dynamic/complex_model_dynamic2";
AnalysisConfig config_tuned;
const std::string shape_range = "shape_range.pbtxt";
config_tuned.EnableUseGpu(100, 0);
config_tuned.SetModel(model_dir + "/model", model_dir + "/params");
config_tuned.CollectShapeRangeInfo(shape_range);
int batch_size = 1;
auto predictor_tuned = CreatePaddlePredictor(config_tuned);
auto check_func = [batch_size](PaddlePredictor *predictor) {
int channels = 3;
int height = 5;
int width = 5;
int input_num = channels * height * width * 1;
float *input = new float[input_num];
memset(input, 0, input_num * sizeof(float));
auto input_names = predictor->GetInputNames();
auto input_t = predictor->GetInputTensor(input_names[0]);
input_t->Reshape({batch_size, channels, height, width});
input_t->copy_from_cpu(input);
auto input_t1 = predictor->GetInputTensor(input_names[1]);
input_t1->Reshape({batch_size, 2, 1, 1});
std::vector<float> first;
for (int i = 0; i < batch_size * 2; i++) first.push_back(1.0);
input_t1->copy_from_cpu(first.data());
auto input_t2 = predictor->GetInputTensor(input_names[2]);
input_t2->Reshape({batch_size, 2, 1, 1});
input_t2->copy_from_cpu(first.data());
ASSERT_TRUE(predictor->ZeroCopyRun());
std::vector<float> out_data;
auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputTensor(output_names[0]);
std::vector<int> output_shape = output_t->shape();
int out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
out_data.resize(out_num);
output_t->copy_to_cpu(out_data.data());
};
check_func(predictor_tuned.get());
predictor_tuned.reset(nullptr);
// check tuned_dynamic_shape
AnalysisConfig config;
config.EnableUseGpu(100, 0);
std::string cache_dir = "tuned_cache";
config.SetOptimCacheDir(cache_dir);
delete_cache_files(cache_dir);
config.SetModel(model_dir + "/model", model_dir + "/params");
config.EnableTunedTensorRtDynamicShape(shape_range, true);
config.EnableTensorRtEngine(
1 << 30, batch_size, 0, AnalysisConfig::Precision::kFloat32, true, false);
auto test_predictor = CreatePaddlePredictor(config);
check_func(test_predictor.get());
}
void TestDynamicClone(bool with_dynamic = true,
bool delete_cache = true,
bool delete_conv_bn = false) {
std::string model_dir =
FLAGS_infer_model + "/conv_bn_swish_split_gelu/conv_bn_swish_split_gelu";
std::string opt_cache_dir = model_dir + "/my_cache";
if (delete_cache) {
delete_cache_files(opt_cache_dir);
}
AnalysisConfig config;
config.EnableUseGpu(100, 0);
std::string buffer_prog, buffer_param;
ReadBinaryFile(model_dir + "/model", &buffer_prog);
ReadBinaryFile(model_dir + "/params", &buffer_param);
config.SetModelBuffer(&buffer_prog[0],
buffer_prog.size(),
&buffer_param[0],
buffer_param.size());
config.SetOptimCacheDir(opt_cache_dir);
// Set the input's min, max, opt shape
config.EnableTensorRtEngine(
1 << 30, 1, 1, AnalysisConfig::Precision::kFloat32, false, false);
if (delete_conv_bn) {
config.pass_builder()->DeletePass("conv_bn_fuse_pass");
}
if (with_dynamic) {
std::map<std::string, std::vector<int>> min_input_shape = {
{"image", {1, 1, 3, 3}}};
std::map<std::string, std::vector<int>> max_input_shape = {
{"image", {1, 1, 10, 10}}};
std::map<std::string, std::vector<int>> opt_input_shape = {
{"image", {1, 1, 3, 3}}};
config.SetTRTDynamicShapeInfo(
min_input_shape, max_input_shape, opt_input_shape);
}
auto predictor = CreatePaddlePredictor(config);
auto input_names = predictor->GetInputNames();
int channels = 1;
int height = 3;
int width = 3;
int input_num = channels * height * width * 1;
float *input = new float[input_num];
memset(input, 0, input_num * sizeof(float));
auto input_t = predictor->GetInputTensor(input_names[0]);
input_t->Reshape({1, channels, height, width});
input_t->copy_from_cpu(input);
ASSERT_TRUE(predictor->ZeroCopyRun());
std::vector<float> out_data;
auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputTensor(output_names[0]);
std::vector<int> output_shape = output_t->shape();
int out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
out_data.resize(out_num);
output_t->copy_to_cpu(out_data.data());
auto predictor2 = predictor->Clone();
auto input_t2 = predictor2->GetInputTensor(input_names[0]);
input_t2->Reshape({1, channels, height, width});
input_t2->copy_from_cpu(input);
ASSERT_TRUE(predictor2->ZeroCopyRun());
std::vector<float> out_data2;
auto output_t2 = predictor2->GetOutputTensor(output_names[0]);
std::vector<int> output_shape2 = output_t2->shape();
int out_num2 = std::accumulate(
output_shape2.begin(), output_shape2.end(), 1, std::multiplies<int>());
out_data2.resize(out_num2);
output_t2->copy_to_cpu(out_data2.data());
ASSERT_TRUE(out_data2.size() == out_data.size());
for (size_t i = 0; i < out_data.size(); i++) {
EXPECT_NEAR(out_data2[i], out_data[i], 1e-5);
}
}
TEST(AnalysisPredictor, trt_dynamic) { TestDynamic(true); }
TEST(AnalysisPredictor, trt_memory_serialize) {
// serialize
TestDynamic(true, true, true);
// deserialize
TestDynamic(true, false, true);
}
TEST(AnalysisPredictor, trt_dynamic2) { TestDynamic2(); }
TEST(AnalysisPredictor, trt_tuned_dynamic) { TestTunedDynamic(); }
TEST(AnalysisPredictor, trt_dynamic_clone) { TestDynamicClone(); }
} // namespace inference
} // namespace paddle
@@ -0,0 +1,49 @@
/* 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. */
#include <glog/logging.h>
#include <gtest/gtest.h>
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/trt_test_helper.h"
namespace paddle {
namespace inference {
TEST(TensorRT, instance_norm) {
std::string model_dir = FLAGS_infer_model + "/instance_norm";
AnalysisConfig config;
int batch_size = 4;
config.EnableUseGpu(100, 0);
config.SetModel(model_dir);
config.EnableTensorRtEngine(
1 << 20, batch_size, 0, AnalysisConfig::Precision::kFloat32, false);
auto predictor = CreatePaddlePredictor(config);
int length = 4;
int input_num = batch_size * length;
float *input = new float[input_num];
memset(input, 1.0, input_num * sizeof(float));
auto input_names = predictor->GetInputNames();
auto input_t = predictor->GetInputTensor(input_names[0]);
input_t->Reshape({batch_size, length});
input_t->copy_from_cpu(input);
ASSERT_TRUE(predictor->ZeroCopyRun());
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,43 @@
/* Copyright (c) 2023 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 <glog/logging.h>
#include <gtest/gtest.h>
#include "test/cpp/inference/api/trt_test_helper.h"
namespace paddle {
namespace inference {
TEST(TensorRT, mark_trt_engine_outputs) {
std::string model_dir = FLAGS_infer_model + "/resnet50";
AnalysisConfig config;
config.SetModel(model_dir);
config.EnableUseGpu(100, 0);
config.EnableTensorRtEngine(
1 << 30, 1, 5, AnalysisConfig::Precision::kFloat32, false, false);
// The name of the tensor that needs to be marked
std::vector<std::string> markOutput = {"pool2d_0.tmp_0"};
config.MarkTrtEngineOutputs(markOutput);
std::vector<std::vector<PaddleTensor>> inputs_all;
auto predictor = CreatePaddlePredictor(config);
SetFakeImageInput(&inputs_all, model_dir, false, "__model__", "");
std::vector<PaddleTensor> outputs;
for (auto &input : inputs_all) {
ASSERT_TRUE(predictor->Run(input, &outputs));
predictor->ClearIntermediateTensor();
}
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,72 @@
/* 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <functional>
#include <numeric>
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/trt_test_helper.h"
namespace paddle_infer {
TEST(PredictorPool, use_gpu) {
std::string model_dir = FLAGS_infer_model + "/" + "mobilenet";
Config config;
config.EnableUseGpu(100, 0);
config.SetModel(model_dir);
config.EnableTensorRtEngine();
config.Exp_DisableTensorRtOPs({"fc"});
config.EnableTensorRtDLA(0);
services::PredictorPool pred_pool(config, 1);
auto predictor = pred_pool.Retrieve(0);
auto input_names = predictor->GetInputNames();
auto input_t = predictor->GetInputHandle(input_names[0]);
std::vector<int> in_shape = {1, 3, 224, 224};
int in_num = std::accumulate(
in_shape.begin(), in_shape.end(), 1, std::multiplies<int>());
std::vector<float> input(in_num, 0);
input_t->Reshape(in_shape);
input_t->CopyFromCpu(input.data());
predictor->Run();
}
TEST(PredictorPool, use_trt_cuda_graph) {
std::string model_dir = FLAGS_infer_model + "/" + "mobilenet";
Config config;
config.EnableUseGpu(100, 0);
config.SetModel(model_dir);
config.EnableTensorRtEngine(
1 << 20, 1, 3, PrecisionType::kFloat32, false, false, true);
config.Exp_DisableTensorRtOPs({"fc"});
config.EnableTensorRtDLA(0);
services::PredictorPool pred_pool(config, 1);
auto predictor = pred_pool.Retrieve(0);
auto input_names = predictor->GetInputNames();
auto input_t = predictor->GetInputHandle(input_names[0]);
std::vector<int> in_shape = {1, 3, 224, 224};
int in_num = std::accumulate(
in_shape.begin(), in_shape.end(), 1, std::multiplies<int>());
std::vector<float> input(in_num, 0);
input_t->Reshape(in_shape);
input_t->CopyFromCpu(input.data());
predictor->Run();
}
} // namespace paddle_infer
@@ -0,0 +1,68 @@
/* 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. */
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <numeric>
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/trt_test_helper.h"
namespace paddle {
namespace inference {
TEST(quant_int8, resnet50) {
std::string model_dir = FLAGS_infer_model;
AnalysisConfig config;
config.EnableUseGpu(1000, 0);
config.SetModel(model_dir);
config.EnableTensorRtEngine(
1 << 30, 1, 1, AnalysisConfig::Precision::kInt8, false, false);
std::map<std::string, std::vector<int>> min_input_shape = {
{"image", {1, 1, 3, 3}}};
std::map<std::string, std::vector<int>> max_input_shape = {
{"image", {1, 1, 10, 10}}};
std::map<std::string, std::vector<int>> opt_input_shape = {
{"image", {1, 1, 3, 3}}};
config.SetTRTDynamicShapeInfo(
min_input_shape, max_input_shape, opt_input_shape);
auto predictor = CreatePaddlePredictor(config);
auto input_names = predictor->GetInputNames();
int channels = 1;
int height = 3;
int width = 3;
int input_num = channels * height * width * 1;
float *input = new float[input_num];
memset(input, 0, input_num * sizeof(float));
auto input_t = predictor->GetInputTensor(input_names[0]);
input_t->Reshape({1, channels, height, width});
input_t->copy_from_cpu(input);
ASSERT_TRUE(predictor->ZeroCopyRun());
std::vector<float> out_data;
auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputTensor(output_names[0]);
std::vector<int> output_shape = output_t->shape();
int out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
out_data.resize(out_num);
output_t->copy_to_cpu(out_data.data());
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,64 @@
/* 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. */
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <numeric>
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/trt_test_helper.h"
namespace paddle {
namespace inference {
TEST(quant_int8, yolov3_resnet50) {
AnalysisConfig config;
config.EnableNewIR(false);
config.EnableUseGpu(100, 0);
config.SetModel(FLAGS_infer_model + "/model", FLAGS_infer_model + "/params");
config.EnableTensorRtEngine(
1 << 30, 1, 3, AnalysisConfig::Precision::kInt8, false, false);
auto predictor = CreatePaddlePredictor(config);
auto input_names = predictor->GetInputNames();
int channels = 3;
int height = 608;
int width = 608;
int input_num = channels * height * width * 1;
float *input = new float[input_num];
int32_t *im_shape = new int32_t[2];
im_shape[0] = 608;
im_shape[1] = 608;
memset(input, 1.0, input_num * sizeof(float));
auto input_t = predictor->GetInputTensor(input_names[0]);
input_t->Reshape({1, channels, height, width});
input_t->copy_from_cpu(input);
auto input_t1 = predictor->GetInputTensor(input_names[1]);
input_t1->Reshape({1, 2});
input_t1->copy_from_cpu(im_shape);
ASSERT_TRUE(predictor->ZeroCopyRun());
std::vector<float> out_data;
auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputTensor(output_names[0]);
std::vector<int> output_shape = output_t->shape();
int out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
out_data.resize(out_num);
output_t->copy_to_cpu(out_data.data());
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,183 @@
/* 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <thread>
#include "paddle/common/flags.h"
#include "paddle/fluid/inference/api/paddle_inference_api.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
// TODO(inference): This case failed in windows with a SEH error, we need to fix
// it.
TEST(ReBindStream_single, use_gpu) {
std::string model_dir = FLAGS_infer_model + "/mobilenet";
AnalysisConfig config;
config.EnableUseGpu(100, 0);
config.SetModel(model_dir);
config.EnableTensorRtEngine();
cudaStream_t stream1, stream2, stream3;
cudaStreamCreate(&stream1);
cudaStreamCreate(&stream2);
cudaStreamCreate(&stream3);
config.SetExecStream(stream1);
auto predictor = paddle_infer::CreatePredictor(config);
auto x_t = predictor->GetInputHandle("x");
x_t->Reshape({1, 3, 224, 224});
std::array<float, 3 * 224 * 224> x_data = {0};
x_t->CopyFromCpu(x_data.data());
ASSERT_TRUE(predictor->Run());
cudaDeviceSynchronize();
ASSERT_TRUE(paddle_infer::experimental::InternalUtils::RunWithExternalStream(
predictor.get(), stream2));
cudaDeviceSynchronize();
ASSERT_TRUE(paddle_infer::experimental::InternalUtils::RunWithExternalStream(
predictor.get(), stream3));
cudaDeviceSynchronize();
}
TEST(ReBindStream_multi, use_gpu) {
std::string model_dir = FLAGS_infer_model + "/mobilenet";
AnalysisConfig config1;
config1.EnableUseGpu(100, 0);
config1.SetModel(model_dir);
config1.EnableTensorRtEngine();
AnalysisConfig config2;
config2.EnableUseGpu(100, 0);
config2.EnableTensorRtEngine();
config2.SetModel(model_dir);
cudaStream_t stream1, stream2, stream3;
cudaStreamCreate(&stream1);
cudaStreamCreate(&stream2);
cudaStreamCreate(&stream3);
config1.SetExecStream(stream1);
config2.SetExecStream(stream1);
auto predictor1 = paddle_infer::CreatePredictor(config1);
auto predictor2 = paddle_infer::CreatePredictor(config2);
std::vector<float> x1(3 * 224 * 224, 1.0);
auto x_t1 = predictor1->GetInputHandle("x");
x_t1->Reshape({1, 3, 224, 224});
x_t1->CopyFromCpu(x1.data());
std::vector<float> x2(3 * 224 * 224, 2.0);
auto x_t2 = predictor2->GetInputHandle("x");
x_t2->Reshape({1, 3, 224, 224});
x_t2->CopyFromCpu(x2.data());
ASSERT_TRUE(predictor1->Run());
cudaStreamSynchronize(stream1);
ASSERT_TRUE(predictor2->Run());
cudaStreamSynchronize(stream1);
ASSERT_TRUE(paddle_infer::experimental::InternalUtils::RunWithExternalStream(
predictor1.get(), stream2));
cudaDeviceSynchronize();
ASSERT_TRUE(paddle_infer::experimental::InternalUtils::RunWithExternalStream(
predictor2.get(), stream2));
cudaDeviceSynchronize();
ASSERT_TRUE(paddle_infer::experimental::InternalUtils::RunWithExternalStream(
predictor1.get(), stream3));
cudaStreamSynchronize(stream3);
ASSERT_TRUE(paddle_infer::experimental::InternalUtils::RunWithExternalStream(
predictor2.get(), stream3));
cudaStreamSynchronize(stream3);
}
TEST(SwitchStream_multi, use_gpu) {
std::string model_dir = FLAGS_infer_model + "/mobilenet";
AnalysisConfig config1;
config1.EnableUseGpu(100, 0);
config1.SetModel(model_dir);
AnalysisConfig config2;
config2.EnableUseGpu(100, 0);
config2.SetModel(model_dir);
AnalysisConfig config3;
config3.EnableUseGpu(100, 0);
config3.SetModel(model_dir);
// config1.EnableTensorRtEngine();
// config2.EnableTensorRtEngine();
// config3.EnableTensorRtEngine();
cudaStream_t stream1, stream2, stream3;
cudaStreamCreate(&stream1);
cudaStreamCreate(&stream2);
cudaStreamCreate(&stream3);
config1.SetExecStream(stream1);
config2.SetExecStream(stream1);
config3.SetExecStream(stream1);
auto predictor1 = paddle_infer::CreatePredictor(config1);
auto predictor2 = paddle_infer::CreatePredictor(config2);
auto predictor3 = paddle_infer::CreatePredictor(config3);
std::vector<float> x1(3 * 224 * 224, 1.0);
auto x_t1 = predictor1->GetInputHandle("x");
x_t1->Reshape({1, 3, 224, 224});
x_t1->CopyFromCpu(x1.data());
std::vector<float> x2(3 * 224 * 224, 2.0);
auto x_t2 = predictor2->GetInputHandle("x");
x_t2->Reshape({1, 3, 224, 224});
x_t2->CopyFromCpu(x2.data());
std::vector<float> x3(3 * 224 * 224, 2.5);
auto x_t3 = predictor3->GetInputHandle("x");
x_t3->Reshape({1, 3, 224, 224});
x_t3->CopyFromCpu(x3.data());
// TODO(wilber): fix.
// NOTE: Must run once on master thread, but why?
// if remove the code, the unit test fail.
ASSERT_TRUE(predictor1->Run());
cudaStreamSynchronize(stream1);
ASSERT_TRUE(predictor2->Run());
cudaStreamSynchronize(stream1);
ASSERT_TRUE(predictor3->Run());
cudaStreamSynchronize(stream1);
auto Run = [&](paddle_infer::Predictor* p,
std::vector<cudaStream_t> streams) {
for (auto s : streams) {
paddle_infer::experimental::InternalUtils::RunWithExternalStream(p, s);
}
};
std::thread p1(Run,
predictor1.get(),
std::vector<cudaStream_t>{
stream1, stream2, stream3, stream3, stream2, stream2});
std::thread p2(Run,
predictor2.get(),
std::vector<cudaStream_t>{
stream1, stream3, stream1, stream2, stream1, stream3});
std::thread p3(Run,
predictor3.get(),
std::vector<cudaStream_t>{
stream1, stream1, stream2, stream3, stream3, stream2});
p1.join();
p2.join();
p3.join();
cudaDeviceSynchronize();
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,46 @@
/* 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. */
#include <glog/logging.h>
#include <gtest/gtest.h>
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/trt_test_helper.h"
namespace paddle {
namespace inference {
TEST(TensorRT, split_converter) {
std::string model_dir = FLAGS_infer_model + "/split_converter";
std::string opt_cache_dir = model_dir + "/_opt_cache";
delete_cache_files(opt_cache_dir);
AnalysisConfig config;
int batch_size = 4;
int channels = 4;
int height = 4;
int width = 4;
config.EnableUseGpu(100, 0);
config.SetModel(model_dir);
config.EnableTensorRtEngine(
1 << 20, batch_size, 1, AnalysisConfig::Precision::kInt8, false, true);
std::map<std::string, std::vector<int>> input_shape;
input_shape["x"] = {batch_size, channels, height, width};
config.SetTRTDynamicShapeInfo(input_shape, input_shape, input_shape, false);
auto predictor = CreatePaddlePredictor(config);
}
} // namespace inference
} // namespace paddle
+178
View File
@@ -0,0 +1,178 @@
/* 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. */
#pragma once
#include <dirent.h>
#include <string>
#include <vector>
#include "glog/logging.h"
#include "gtest/gtest.h"
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle {
namespace inference {
PD_DEFINE_bool(use_tensorrt, true, "Test the performance of TensorRT engine.");
PD_DEFINE_string(prog_filename, "", "Name of model file.");
PD_DEFINE_string(param_filename, "", "Name of parameters file.");
template <typename ConfigType>
void SetConfig(ConfigType* config,
std::string model_dir,
bool use_gpu,
bool use_tensorrt = false,
int batch_size = -1) {
if (!FLAGS_prog_filename.empty() && !FLAGS_param_filename.empty()) {
config->prog_file = model_dir + "/" + FLAGS_prog_filename;
config->param_file = model_dir + "/" + FLAGS_param_filename;
} else {
config->model_dir = model_dir;
}
if (use_gpu) {
config->use_gpu = true;
config->device = 0;
config->fraction_of_gpu_memory = 0.15;
}
}
template <>
void SetConfig<AnalysisConfig>(AnalysisConfig* config,
std::string model_dir,
bool use_gpu,
bool use_tensorrt,
int batch_size) {
if (!FLAGS_prog_filename.empty() && !FLAGS_param_filename.empty()) {
config->SetModel(model_dir + "/" + FLAGS_prog_filename,
model_dir + "/" + FLAGS_param_filename);
} else {
config->SetModel(model_dir);
}
if (use_gpu) {
config->EnableUseGpu(100, 0);
if (use_tensorrt) {
config->EnableTensorRtEngine(
1 << 10, batch_size, 3, AnalysisConfig::Precision::kFloat32, false);
config->pass_builder()->DeletePass("conv_bn_fuse_pass");
config->pass_builder()->DeletePass("fc_fuse_pass");
config->pass_builder()->TurnOnDebug();
} else {
config->EnableCUDNN();
config->SwitchIrOptim();
}
}
}
void profile(std::string model_dir, bool use_analysis, bool use_tensorrt) {
std::vector<std::vector<PaddleTensor>> inputs_all;
if (!FLAGS_prog_filename.empty() && !FLAGS_param_filename.empty()) {
SetFakeImageInput(&inputs_all,
model_dir,
true,
FLAGS_prog_filename,
FLAGS_param_filename);
} else {
SetFakeImageInput(&inputs_all, model_dir, false, "__model__", "");
}
std::vector<std::vector<PaddleTensor>> outputs;
if (use_analysis || use_tensorrt) {
AnalysisConfig config;
config.EnableUseGpu(100, 0);
config.pass_builder()->TurnOnDebug();
SetConfig<AnalysisConfig>(
&config, model_dir, true, use_tensorrt, FLAGS_batch_size);
TestPrediction(reinterpret_cast<PaddlePredictor::Config*>(&config),
inputs_all,
&outputs,
FLAGS_num_threads,
true);
} else {
NativeConfig config;
SetConfig<NativeConfig>(&config, model_dir, true, false);
TestPrediction(reinterpret_cast<PaddlePredictor::Config*>(&config),
inputs_all,
&outputs,
FLAGS_num_threads,
false);
}
}
void compare(std::string model_dir, bool use_tensorrt) {
std::vector<std::vector<PaddleTensor>> inputs_all;
if (!FLAGS_prog_filename.empty() && !FLAGS_param_filename.empty()) {
SetFakeImageInput(&inputs_all,
model_dir,
true,
FLAGS_prog_filename,
FLAGS_param_filename);
} else {
SetFakeImageInput(&inputs_all, model_dir, false, "__model__", "");
}
AnalysisConfig analysis_config;
SetConfig<AnalysisConfig>(
&analysis_config, model_dir, true, use_tensorrt, FLAGS_batch_size);
CompareNativeAndAnalysis(
reinterpret_cast<const PaddlePredictor::Config*>(&analysis_config),
inputs_all);
}
void compare_continuous_input(std::string model_dir, bool use_tensorrt) {
AnalysisConfig analysis_config;
SetConfig<AnalysisConfig>(
&analysis_config, model_dir, true, use_tensorrt, FLAGS_batch_size);
auto config =
reinterpret_cast<const PaddlePredictor::Config*>(&analysis_config);
auto native_pred = CreateTestPredictor(config, false);
auto analysis_pred = CreateTestPredictor(config, true);
for (int i = 0; i < 20; i++) {
std::vector<std::vector<PaddleTensor>> inputs_all;
if (!FLAGS_prog_filename.empty() && !FLAGS_param_filename.empty()) {
SetFakeImageInput(&inputs_all,
model_dir,
true,
FLAGS_prog_filename,
FLAGS_param_filename,
nullptr,
i);
} else {
SetFakeImageInput(
&inputs_all, model_dir, false, "__model__", "", nullptr, i);
}
CompareNativeAndAnalysis(
native_pred.get(), analysis_pred.get(), inputs_all);
}
}
void delete_cache_files(std::string path) {
DIR* dir = opendir(path.c_str());
if (dir == NULL) return;
struct dirent* ptr;
while ((ptr = readdir(dir)) != NULL) {
if (std::strcmp(ptr->d_name, ".") == 0 ||
std::strcmp(ptr->d_name, "..") == 0) {
continue;
} else if (ptr->d_type == 8) {
std::string file_rm = path + "/" + ptr->d_name;
remove(file_rm.c_str());
}
}
closedir(dir);
remove(path.c_str());
}
} // namespace inference
} // namespace paddle
@@ -0,0 +1,89 @@
/* Copyright (c) 2023 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <cmath>
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/tester_helper.h"
namespace paddle_infer {
static const std::vector<float> TRUTH_VALUES = {
127.779f, 738.165f, 1013.22f, -438.17f, 366.401f, 927.659f, 736.222f,
-633.684f, -329.927f, -430.155f, -633.062f, -146.548f, -1324.28f, -1349.36f,
-242.675f, 117.448f, -801.723f, -391.514f, -404.818f, 454.16f, 515.48f,
-133.031f, 69.293f, 590.096f, -1434.69f, -1070.89f, 307.074f, 400.525f,
-316.12f, -587.125f, -161.056f, 800.363f, -96.4708f, 748.706f, 868.174f,
-447.938f, 112.737f, 1127.2f, 47.4355f, 677.72f, 593.186f, -336.4f,
551.362f, 397.823f, 78.3979f, -715.398f, 405.969f, 404.256f, 246.019f,
-8.42969f, 131.365f, -648.051f};
void PrepareInput(std::shared_ptr<Predictor> predictor) {
const int batch = 1;
const int channel = 3;
const int height = 318;
const int width = 318;
const int input_num = batch * channel * height * width;
std::vector<float> input(input_num, 1);
auto input_names = predictor->GetInputNames();
auto input_t = predictor->GetInputHandle(input_names[0]);
input_t->Reshape({batch, channel, height, width});
input_t->CopyFromCpu(input.data());
}
void CompareOutput(std::shared_ptr<Predictor> predictor) {
auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputHandle(output_names[0]);
std::vector<int> output_shape = output_t->shape();
size_t out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
std::vector<float> out_data;
out_data.resize(out_num);
output_t->CopyToCpu(out_data.data());
float* data_o = out_data.data();
for (size_t j = 0; j < out_num; j += 10) {
EXPECT_NEAR(
(data_o[j] - TRUTH_VALUES[j / 10]) / TRUTH_VALUES[j / 10], 0., 10e-3);
}
}
TEST(xpu_config, inference) {
size_t l3_size = 10 * 1024 * 1024;
XpuConfig xpu_config;
xpu_config.l3_size = l3_size;
std::string model_dir = FLAGS_infer_model + "/" + "model";
Config config;
config.SetModel(model_dir + "/model", model_dir + "/params");
config.EnableXpu();
config.SetXpuConfig(xpu_config);
XpuConfig xpu_config_test = config.xpu_config();
PADDLE_ENFORCE_EQ(xpu_config_test.l3_size,
l3_size,
common::errors::InvalidArgument(
"xpu_config_test.l3_size %d is different from our "
"expected value l3_size %d.",
xpu_config_test.l3_size,
l3_size));
auto predictor = CreatePredictor(config);
PrepareInput(predictor);
predictor->Run();
CompareOutput(predictor);
}
} // namespace paddle_infer
@@ -0,0 +1,269 @@
/* Copyright (c) 2023 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 <glog/logging.h>
#include <gtest/gtest.h>
#include <cmath>
#include "paddle/common/enforce.h"
#include "paddle/common/flags.h"
#include "test/cpp/inference/api/tester_helper.h"
#include "xpu/runtime.h"
#include "xpu/xdnn.h"
namespace paddle_infer {
static const std::vector<float> TRUTH_VALUES = {
127.779f, 738.165f, 1013.22f, -438.17f, 366.401f, 927.659f, 736.222f,
-633.684f, -329.927f, -430.155f, -633.062f, -146.548f, -1324.28f, -1349.36f,
-242.675f, 117.448f, -801.723f, -391.514f, -404.818f, 454.16f, 515.48f,
-133.031f, 69.293f, 590.096f, -1434.69f, -1070.89f, 307.074f, 400.525f,
-316.12f, -587.125f, -161.056f, 800.363f, -96.4708f, 748.706f, 868.174f,
-447.938f, 112.737f, 1127.2f, 47.4355f, 677.72f, 593.186f, -336.4f,
551.362f, 397.823f, 78.3979f, -715.398f, 405.969f, 404.256f, 246.019f,
-8.42969f, 131.365f, -648.051f};
void PrepareInput(std::shared_ptr<Predictor> predictor) {
const int batch = 1;
const int channel = 3;
const int height = 318;
const int width = 318;
const int input_num = batch * channel * height * width;
std::vector<float> input(input_num, 1);
auto input_names = predictor->GetInputNames();
auto input_t = predictor->GetInputHandle(input_names[0]);
input_t->Reshape({batch, channel, height, width});
input_t->CopyFromCpu(input.data());
}
void CompareOutput(std::shared_ptr<Predictor> predictor) {
auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputHandle(output_names[0]);
std::vector<int> output_shape = output_t->shape();
size_t out_num = std::accumulate(
output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
std::vector<float> out_data;
out_data.resize(out_num);
output_t->CopyToCpu(out_data.data());
float* data_o = out_data.data();
for (size_t j = 0; j < out_num; j += 10) {
EXPECT_NEAR(
(data_o[j] - TRUTH_VALUES[j / 10]) / TRUTH_VALUES[j / 10], 0., 10e-3);
}
}
Config InferXpuConfig() {
std::string model_dir = FLAGS_infer_model + "/" + "model";
Config config;
config.SetModel(model_dir + "/model", model_dir + "/params");
config.EnableXpu();
return config;
}
TEST(resnet50_xpu, basic) {
Config config = InferXpuConfig();
auto predictor = CreatePredictor(config);
PrepareInput(predictor);
predictor->Run();
CompareOutput(predictor);
}
#define RUN_WITH_RUNTIME_CONFIG(idx_, config_) \
Config config##idx_ = InferXpuConfig(); \
auto predictor##idx_ = CreatePredictor(config##idx_); \
PrepareInput(predictor##idx_); \
experimental::InternalUtils::RunWithRuntimeConfig(predictor##idx_.get(), \
&config_); \
CompareOutput(predictor##idx_); \
PADDLE_ENFORCE_EQ( \
predictor##idx_->GetExecStream(), \
config_.stream, \
common::errors::InvalidArgument( \
"predictor##idx_->GetExecStream() is not equal with " \
"config_.stream while predictor##idx_->GetExecStream() " \
"is %d and config_.stream is %d", \
predictor##idx_->GetExecStream(), \
config_.stream));
TEST(runtime_stream, null_stream) {
experimental::XpuRuntimeConfig xpu_runtime_config;
xpu_runtime_config.context = nullptr;
xpu_runtime_config.stream = nullptr;
xpu_runtime_config.l3_size = 0;
xpu_runtime_config.l3_ptr = nullptr;
xpu_runtime_config.l3_autotune_size = 0;
RUN_WITH_RUNTIME_CONFIG(0, xpu_runtime_config);
}
TEST(runtime_stream, new_stream) {
void* stream = nullptr;
xpu_stream_create(&stream);
CHECK_NOTNULL(stream);
{
experimental::XpuRuntimeConfig xpu_runtime_config;
xpu_runtime_config.context = nullptr;
xpu_runtime_config.stream = stream;
xpu_runtime_config.l3_size = 0;
xpu_runtime_config.l3_ptr = nullptr;
xpu_runtime_config.l3_autotune_size = 0;
RUN_WITH_RUNTIME_CONFIG(0, xpu_runtime_config);
}
xpu_stream_destroy(stream);
}
TEST(runtime_stream, 2_null_stream) {
experimental::XpuRuntimeConfig xpu_runtime_config;
xpu_runtime_config.context = nullptr;
xpu_runtime_config.stream = nullptr;
xpu_runtime_config.l3_size = 0;
xpu_runtime_config.l3_ptr = nullptr;
xpu_runtime_config.l3_autotune_size = 0;
RUN_WITH_RUNTIME_CONFIG(0, xpu_runtime_config);
RUN_WITH_RUNTIME_CONFIG(1, xpu_runtime_config);
}
TEST(runtime_stream, null_and_new_stream) {
experimental::XpuRuntimeConfig xpu_runtime_config0;
xpu_runtime_config0.context = nullptr;
xpu_runtime_config0.stream = nullptr;
xpu_runtime_config0.l3_size = 0;
xpu_runtime_config0.l3_ptr = nullptr;
xpu_runtime_config0.l3_autotune_size = 0;
void* stream = nullptr;
xpu_stream_create(&stream);
CHECK_NOTNULL(stream);
{
experimental::XpuRuntimeConfig xpu_runtime_config1;
xpu_runtime_config1.context = nullptr;
xpu_runtime_config1.stream = stream;
xpu_runtime_config1.l3_size = 0;
xpu_runtime_config1.l3_ptr = nullptr;
xpu_runtime_config1.l3_autotune_size = 0;
RUN_WITH_RUNTIME_CONFIG(0, xpu_runtime_config0);
RUN_WITH_RUNTIME_CONFIG(1, xpu_runtime_config1);
}
xpu_stream_destroy(stream);
}
TEST(runtime_stream, 2_new_same_stream) {
void* stream = nullptr;
xpu_stream_create(&stream);
CHECK_NOTNULL(stream);
experimental::XpuRuntimeConfig xpu_runtime_config;
xpu_runtime_config.context = nullptr;
xpu_runtime_config.stream = stream;
xpu_runtime_config.l3_size = 0;
xpu_runtime_config.l3_ptr = nullptr;
xpu_runtime_config.l3_autotune_size = 0;
{
RUN_WITH_RUNTIME_CONFIG(0, xpu_runtime_config);
RUN_WITH_RUNTIME_CONFIG(1, xpu_runtime_config);
}
xpu_stream_destroy(stream);
}
TEST(runtime_stream, 2_new_different_stream) {
void* stream0 = nullptr;
xpu_stream_create(&stream0);
CHECK_NOTNULL(stream0);
experimental::XpuRuntimeConfig xpu_runtime_config0;
xpu_runtime_config0.context = nullptr;
xpu_runtime_config0.stream = stream0;
xpu_runtime_config0.l3_size = 0;
xpu_runtime_config0.l3_ptr = nullptr;
xpu_runtime_config0.l3_autotune_size = 0;
void* stream1 = nullptr;
xpu_stream_create(&stream1);
CHECK_NOTNULL(stream1);
experimental::XpuRuntimeConfig xpu_runtime_config1;
xpu_runtime_config1.context = nullptr;
xpu_runtime_config1.stream = stream1;
xpu_runtime_config1.l3_size = 0;
xpu_runtime_config1.l3_ptr = nullptr;
xpu_runtime_config1.l3_autotune_size = 0;
{
RUN_WITH_RUNTIME_CONFIG(0, xpu_runtime_config0);
RUN_WITH_RUNTIME_CONFIG(1, xpu_runtime_config1);
}
xpu_stream_destroy(stream0);
xpu_stream_destroy(stream1);
}
void RunPredictorWithRuntimeConfig(
std::shared_ptr<Predictor> predictor,
experimental::XpuRuntimeConfig runtime_config) {
PrepareInput(predictor);
experimental::InternalUtils::RunWithRuntimeConfig(predictor.get(),
&runtime_config);
CompareOutput(predictor);
PADDLE_ENFORCE_EQ(predictor->GetExecStream(),
runtime_config.stream,
common::errors::InvalidArgument(
"predictor->GetExecStream() is not equal with "
"runtime_config.stream"));
}
TEST(runtime_stream, 2_thread) {
void* stream0 = nullptr;
xpu_stream_create(&stream0);
CHECK_NOTNULL(stream0);
experimental::XpuRuntimeConfig xpu_runtime_config0;
xpu_runtime_config0.context = nullptr;
xpu_runtime_config0.stream = stream0;
xpu_runtime_config0.l3_size = 0;
xpu_runtime_config0.l3_ptr = nullptr;
xpu_runtime_config0.l3_autotune_size = 0;
void* stream1 = nullptr;
xpu_stream_create(&stream1);
CHECK_NOTNULL(stream1);
experimental::XpuRuntimeConfig xpu_runtime_config1;
xpu_runtime_config1.context = nullptr;
xpu_runtime_config1.stream = stream1;
xpu_runtime_config1.l3_size = 0;
xpu_runtime_config1.l3_ptr = nullptr;
xpu_runtime_config1.l3_autotune_size = 0;
{
RUN_WITH_RUNTIME_CONFIG(0, xpu_runtime_config0);
RUN_WITH_RUNTIME_CONFIG(1, xpu_runtime_config1);
std::thread t0(
RunPredictorWithRuntimeConfig, predictor0, xpu_runtime_config0);
std::thread t1(
RunPredictorWithRuntimeConfig, predictor1, xpu_runtime_config1);
t0.join();
t1.join();
}
xpu_stream_destroy(stream0);
xpu_stream_destroy(stream1);
}
TEST(runtime_context, new_context) {
auto* context = baidu::xpu::api::create_context();
CHECK_NOTNULL(context);
{
experimental::XpuRuntimeConfig xpu_runtime_config;
xpu_runtime_config.context = context;
xpu_runtime_config.stream = nullptr;
xpu_runtime_config.l3_size = 0;
xpu_runtime_config.l3_ptr = nullptr;
xpu_runtime_config.l3_autotune_size = 0;
RUN_WITH_RUNTIME_CONFIG(0, xpu_runtime_config);
}
baidu::xpu::api::destroy_context(context);
}
} // namespace paddle_infer