diff --git a/src/io/api_paddle_mobile.cc b/src/io/api_paddle_mobile.cc index dd3b1b7317ecbebc1f6c65da66db65b7368f23f1..edc36514cdb8048c1563119c42c41a556c17ef07 100644 --- a/src/io/api_paddle_mobile.cc +++ b/src/io/api_paddle_mobile.cc @@ -110,6 +110,74 @@ bool PaddleMobilePredictor::Run( return true; } +#ifdef PADDLE_MOBILE_FPGA +template +bool PaddleMobilePredictor::Run( + const std::vector &inputs, + std::vector *output_data, std::vector *index_data, + int batch_size) { + if (inputs.empty()) { + LOG(kLOG_ERROR) << "At least one output should be set with tensors' names."; + return false; + } + auto input = inputs[0]; + + if (input.shape.size() != 4) { + LOG(kLOG_ERROR) << "input shape not equal to 4!"; + return false; + } + std::vector dims; + for (auto d : input.shape) { + dims.push_back(static_cast(d)); + } + + // use tensor + framework::DDim ddim = + framework::make_ddim({dims[0], dims[1], dims[2], dims[3]}); + + framework::Tensor input_tensor; + input_tensor.Resize(ddim); + int input_length = framework::product(ddim); + auto input_ptr = input_tensor.mutable_data(); + + memcpy(input_ptr, static_cast(input.data.data()), + input_length * sizeof(T)); + paddle_mobile_->Predict(input_tensor); + auto num_result = index_data->size(); + if (output_data->size() != num_result) { + LOG(kLOG_ERROR) << "index and output number don't match"; + return false; + } + + for (int i = 0; i < num_result; i++) { + auto output_tensor = paddle_mobile_->FetchResult((*index_data)[i]); + + if (output_data->empty()) { + LOG(kLOG_ERROR) + << "At least one output should be set with tensors' names."; + return false; + } + + auto &output = (*output_data)[i]; + int output_length = output_tensor->numel(); + std::vector tensor_shape = + framework::vectorize(output_tensor->dims()); + + for (auto d : tensor_shape) { + output.shape.push_back(static_cast(d)); + } + + if (output.data.length() < output_length * sizeof(T)) { + output.data.Resize(output_length * sizeof(T)); + } + + memcpy(output.data.data(), output_tensor->template data(), + output_length * sizeof(T)); + } + + return true; +} +#endif template PaddleMobilePredictor::~PaddleMobilePredictor() { paddle_mobile_->Clear(); diff --git a/src/io/api_paddle_mobile.h b/src/io/api_paddle_mobile.h index bca169a2ed7786ce5dbd58ddecf6d637e4c4854c..d1713ea2fe2cb204d2487151c69c050548eb51a3 100644 --- a/src/io/api_paddle_mobile.h +++ b/src/io/api_paddle_mobile.h @@ -31,7 +31,11 @@ class PaddleMobilePredictor : public PaddlePredictor { bool Run(const std::vector& inputs, std::vector* output_data, int batch_size = -1) override; - +#ifdef PADDLE_MOBILE_FPGA + bool Run(const std::vector& inputs, + std::vector* output_data, std::vector* index_data, + int batch_size = -1) override; +#endif ~PaddleMobilePredictor() override; private: diff --git a/src/io/paddle_inference_api.h b/src/io/paddle_inference_api.h index afbd93dede6b5406f572c3b20b48a5904660e5e3..2ba85a58ac37faf9601ed12fb98293a4c46352ea 100644 --- a/src/io/paddle_inference_api.h +++ b/src/io/paddle_inference_api.h @@ -26,8 +26,16 @@ limitations under the License. */ #include #include +// #define PADDLE_MOBILE_FPGA + namespace paddle_mobile { +#ifdef PADDLE_MOBILE_FPGA +namespace fpga { +int open_device(); +} +#endif + enum PaddleDType { FLOAT32, INT64, @@ -107,6 +115,11 @@ class PaddlePredictor { std::string prog_file; std::string param_file; }; +#ifdef PADDLE_MOBILE_FPGA + virtual bool Run(const std::vector& inputs, + std::vector* output_data, + std::vector* index_data, int batch_size = -1) = 0; +#endif protected: PaddlePredictor() = default; diff --git a/src/operators/detection_ops.cpp b/src/operators/detection_ops.cpp index 38a149a355f089b9c270b00e783ca0a28ae51062..630b672225f139891d136844558f9e418ac54508 100644 --- a/src/operators/detection_ops.cpp +++ b/src/operators/detection_ops.cpp @@ -22,6 +22,7 @@ namespace operators { template void AnchorGeneratorOp::InferShape() const { const auto &input_dims = this->param_.input_->dims(); + // DLOG << "AnchorGenerator input dim =" << input_dims.size(); PADDLE_MOBILE_ENFORCE(input_dims.size() == 4, "The layout of input is NCHW."); const auto &anchor_sizes = this->param_.anchor_sizes_; const auto &aspect_ratios = this->param_.aspect_ratios_; @@ -98,3 +99,15 @@ REGISTER_OPERATOR_CPU(psroi_pool, ops::PSRoiPoolOp); REGISTER_OPERATOR_CPU(roi_perspective_transform, ops::RoiPerspectiveOp); #endif #endif + +#ifdef PADDLE_MOBILE_FPGA +#ifdef ANCHOR_GENERATOR_OP +REGISTER_OPERATOR_FPGA(anchor_generator, ops::AnchorGeneratorOp); +#endif +#ifdef PROPOSAL_OP +REGISTER_OPERATOR_FPGA(generate_proposals, ops::ProposalOp); +#endif +#ifdef PSROI_POOL_OP +REGISTER_OPERATOR_FPGA(psroi_pool, ops::PSRoiPoolOp); +#endif +#endif diff --git a/src/operators/kernel/detection_kernel.h b/src/operators/kernel/detection_kernel.h index 3d669b2d3d19a40928d54816b65deca6c5169673..de3c5a3a3ddd15f8485c92185c131210ba3899f9 100644 --- a/src/operators/kernel/detection_kernel.h +++ b/src/operators/kernel/detection_kernel.h @@ -28,11 +28,11 @@ class AnchorGeneratorParam : public OpParam { AnchorGeneratorParam(const VariableNameMap &inputs, const VariableNameMap &outputs, const AttributeMap &attrs, const Scope &scope) { - input_ = OpParam::GetVarValue("Input", inputs, scope); + input_ = OpParam::GetVarValue("Input", inputs, scope); output_anchors_ = - OpParam::GetVarValue("Anchors", outputs, scope); + OpParam::GetVarValue("Anchors", outputs, scope); output_variances_ = - OpParam::GetVarValue("Variances", outputs, scope); + OpParam::GetVarValue("Variances", outputs, scope); anchor_sizes_ = OpParam::GetAttr>("anchor_sizes", attrs); aspect_ratios_ = @@ -65,14 +65,16 @@ class ProposalParam : public OpParam { public: ProposalParam(const VariableNameMap &inputs, const VariableNameMap &outputs, const AttributeMap &attrs, const Scope &scope) { - scores_ = OpParam::GetVarValue("Scores", inputs, scope); + scores_ = + OpParam::GetVarValue("Scores", inputs, scope); bbox_deltas_ = - OpParam::GetVarValue("BboxDeltas", inputs, scope); - im_info_ = OpParam::GetVarValue("ImInfo", inputs, scope); + OpParam::GetVarValue("BboxDeltas", inputs, scope); + im_info_ = + OpParam::GetVarValue("ImInfo", inputs, scope); anchors_ = - OpParam::GetVarValue("Anchors", inputs, scope); + OpParam::GetVarValue("Anchors", inputs, scope); variances_ = - OpParam::GetVarValue("Variances", inputs, scope); + OpParam::GetVarValue("Variances", inputs, scope); rpn_rois_ = OpParam::GetVarValue("RpnRois", outputs, scope); @@ -112,10 +114,10 @@ class PSRoiPoolParam : public OpParam { public: PSRoiPoolParam(const VariableNameMap &inputs, const VariableNameMap &outputs, const AttributeMap &attrs, const Scope &scope) { - input_x_ = OpParam::GetVarValue("X", inputs, scope); + input_x_ = OpParam::GetVarValue("X", inputs, scope); input_rois_ = OpParam::GetVarValue("ROIs", inputs, scope); - output_ = OpParam::GetVarValue("Out", outputs, scope); + output_ = OpParam::GetVarValue("Out", outputs, scope); output_channels_ = OpParam::GetAttr("output_channels", attrs); pooled_height_ = OpParam::GetAttr("pooled_height", attrs); @@ -143,10 +145,10 @@ class RoiPerspectiveParam : public OpParam { RoiPerspectiveParam(const VariableNameMap &inputs, const VariableNameMap &outputs, const AttributeMap &attrs, const Scope &scope) { - input_x_ = OpParam::GetVarValue("X", inputs, scope); + input_x_ = OpParam::GetVarValue("X", inputs, scope); input_rois_ = OpParam::GetVarValue("ROIs", inputs, scope); - output_ = OpParam::GetVarValue("Out", outputs, scope); + output_ = OpParam::GetVarValue("Out", outputs, scope); spatial_scale_ = OpParam::GetAttr("spatial_scale", attrs); transformed_height_ = OpParam::GetAttr("transformed_height", attrs); diff --git a/src/operators/kernel/fpga/V1/anchor_generator_kernel.cpp b/src/operators/kernel/fpga/V1/anchor_generator_kernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a97f26353ac8ca762dbbfdb95f5a5c081eedd19c --- /dev/null +++ b/src/operators/kernel/fpga/V1/anchor_generator_kernel.cpp @@ -0,0 +1,39 @@ +/* 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. */ + +#ifdef ANCHOR_GENERATOR_OP + +#include +#include "operators/kernel/detection_kernel.h" + +namespace paddle_mobile { +namespace operators { + +template <> +bool AnchorGeneratorKernel::Init( + AnchorGeneratorParam *param) { + return true; + +} + +template <> +void AnchorGeneratorKernel::Compute( + const AnchorGeneratorParam ¶m) { + // TODO(hjchen2) +} + +} // namespace operators +} // namespace paddle_mobile + +#endif // ANCHOR_GENERATOR_OP diff --git a/src/operators/kernel/fpga/V1/proposal_kernel.cpp b/src/operators/kernel/fpga/V1/proposal_kernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d16e057da97eec8d4509eaf8be9f98696a8bed40 --- /dev/null +++ b/src/operators/kernel/fpga/V1/proposal_kernel.cpp @@ -0,0 +1,36 @@ +/* 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. */ + +#ifdef PROPOSAL_OP + +#include +#include "operators/kernel/detection_kernel.h" + +namespace paddle_mobile { +namespace operators { + +template <> +bool ProposalKernel::Init(ProposalParam *param) { + return true; +} + +template <> +void ProposalKernel::Compute(const ProposalParam ¶m) { + // TODO(hjchen2) +} + +} // namespace operators +} // namespace paddle_mobile + +#endif // PROPOSAL_OP diff --git a/src/operators/kernel/fpga/V1/psroi_pool_kernel.cpp b/src/operators/kernel/fpga/V1/psroi_pool_kernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8bb1de6b13c90c0b5b3d0bbeaa0106ad2e9be30a --- /dev/null +++ b/src/operators/kernel/fpga/V1/psroi_pool_kernel.cpp @@ -0,0 +1,36 @@ +/* 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. */ + +#ifdef PSROI_POOL_OP + +#include +#include "operators/kernel/detection_kernel.h" + +namespace paddle_mobile { +namespace operators { + +template <> +bool PSRoiPoolKernel::Init(PSRoiPoolParam *param) { + return true; +} + +template <> +void PSRoiPoolKernel::Compute(const PSRoiPoolParam ¶m) { + // TODO(hjchen2) +} + +} // namespace operators +} // namespace paddle_mobile + +#endif // PSROI_POOL_OP diff --git a/src/operators/kernel/fpga/V1/reshape2_kernel.cpp b/src/operators/kernel/fpga/V1/reshape2_kernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5370df6899cea632dbc2d8f3434760eb7e0c4c38 --- /dev/null +++ b/src/operators/kernel/fpga/V1/reshape2_kernel.cpp @@ -0,0 +1,35 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#ifdef RESHAPE2_OP + +#include "operators/kernel/reshape2_kernel.h" + +namespace paddle_mobile { +namespace operators { + +template <> +bool Reshape2Kernel::Init(Reshape2Param *param) { + return true; +} + +template <> +void Reshape2Kernel::Compute(const Reshape2Param ¶m) { + return; +} + +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/src/operators/kernel/fpga/V1/slice_kernel.cpp b/src/operators/kernel/fpga/V1/slice_kernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea5c3ebca4b78e6052284df94fe3292e4002fcc7 --- /dev/null +++ b/src/operators/kernel/fpga/V1/slice_kernel.cpp @@ -0,0 +1,30 @@ +/* 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. */ + +#ifdef SLICE_OP + +#include "operators/kernel/slice_kernel.h" + +namespace paddle_mobile { +namespace operators { + +template <> +bool SliceKernel::Init(SliceParam* param) { + return true; +} +template <> +void SliceKernel::Compute(const SliceParam& param) {} +} // namespace operators +} // namespace paddle_mobile +#endif diff --git a/src/operators/reshape2_op.cpp b/src/operators/reshape2_op.cpp index d1623076570d466fc53f885374060c5e744365ed..c0f2a2450d29b2f95edb2ff049cea8280913afc8 100644 --- a/src/operators/reshape2_op.cpp +++ b/src/operators/reshape2_op.cpp @@ -43,5 +43,8 @@ REGISTER_OPERATOR_CPU(reshape2, ops::Reshape2Op); #ifdef PADDLE_MOBILE_MALI_GPU REGISTER_OPERATOR_MALI_GPU(reshape2, ops::Reshape2Op); #endif +#ifdef PADDLE_MOBILE_FPGA +REGISTER_OPERATOR_FPGA(reshape2, ops::Reshape2Op); +#endif #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f3dffbad1c065561d86da0e976792d206198c61e..fdd7c46fedc98b3f1811cd10ffe6bcec7d0e3a46 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -74,6 +74,9 @@ if (CON GREATER -1) ADD_EXECUTABLE(test-densebox fpga/test_densebox_combine.cpp test_helper.h test_include.h executor_for_test.h) target_link_libraries(test-densebox paddle-mobile) + ADD_EXECUTABLE(test-rfcn fpga/test_rfcn.cpp test_helper.h test_include.h executor_for_test.h) + target_link_libraries(test-rfcn paddle-mobile) + set(FOUND_MATCH ON) endif () diff --git a/test/fpga/test_rfcn.cpp b/test/fpga/test_rfcn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4d7657bf0b06a2954914da56a863e1c417ba176 --- /dev/null +++ b/test/fpga/test_rfcn.cpp @@ -0,0 +1,52 @@ +/* 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 +#include "../test_helper.h" +#include "../test_include.h" + +#ifdef PADDLE_MOBILE_FPGA_V1 +#include "fpga/V1/api.h" +#endif +#ifdef PADDLE_MOBILE_FPGA_V2 +#include "fpga/V2/api.h" +#endif + +// static const char *g_densebox_combine = "../models/densebox"; +static const char *g_densebox_combine = "../models/rfcn"; +int main() { + paddle_mobile::fpga::open_device(); + paddle_mobile::PaddleMobile paddle_mobile; + // paddle_mobile.SetThreadNum(4); + if (paddle_mobile.Load(std::string(g_densebox_combine) + "/model", + std::string(g_densebox_combine) + "/params", true, + false, 1, true)) { + // std::vector input; + // std::vector dims{1, 3, 512, 1024}; + // GetInput(g_test_image_1x3x224x224_banana, &input, dims); + + // auto vec_result = paddle_mobile.Predict(input, dims); + return 0; + + Tensor input_tensor; + SetupTensor(&input_tensor, {1, 3, 512, 1024}, static_cast(0), + static_cast(1)); + // readStream(g_image_src_float, + // input_tensor.mutable_data({1, 3, 224, 224})); + paddle_mobile.FeedData(input_tensor); + paddle_mobile.Predict_To(-1); + } + + return 0; +} diff --git a/tools/op.cmake b/tools/op.cmake index 89c23e47ca4ad98cd6b10d48e489f41c8319fb60..0ceacaa15f6a37f580ea415401d76701908e8455 100644 --- a/tools/op.cmake +++ b/tools/op.cmake @@ -126,6 +126,11 @@ if (CON GREATER -1) set(RESHAPE_OP ON) set(FUSION_CONVADDBNRELU_OP ON) set(FUSION_CONVADDBN_OP ON) + set(RESHAPE2_OP ON) + set(PSROI_POOL_OP ON) + set(PROPOSAL_OP ON) + set(ANCHOR_GENERATOR_OP ON) + set(SLICE_OP ON) set(FOUND_MATCH ON) endif()