diff --git a/src/jni/paddle_mobile_jni.cpp b/src/jni/paddle_mobile_jni.cpp index 66150e24e0ac957773161904948c10cf4637ee42..c8ed491672920d85adafa28316663ede64a6dcc9 100644 --- a/src/jni/paddle_mobile_jni.cpp +++ b/src/jni/paddle_mobile_jni.cpp @@ -206,6 +206,13 @@ JNIEXPORT jfloatArray JNICALL Java_com_baidu_paddle_PML_predictYuv( return result; } +JNIEXPORT void JNICALL Java_com_baidu_paddle_PML_setThread(JNIEnv *env, + jclass thiz, + jint threadCount) { + ANDROIDLOGI("setThreadCount %d", threadCount); + getPaddleMobileInstance()->SetThreadNum((int)threadCount); +} + JNIEXPORT void JNICALL Java_com_baidu_paddle_PML_clear(JNIEnv *env, jclass thiz) { getPaddleMobileInstance()->Clear(); diff --git a/src/jni/paddle_mobile_jni.h b/src/jni/paddle_mobile_jni.h index 06fabe04c739dfcee06110a3592a88591e3d37b9..4fd62a6d56c71dfc748cc967244bc830abb74a80 100644 --- a/src/jni/paddle_mobile_jni.h +++ b/src/jni/paddle_mobile_jni.h @@ -64,6 +64,12 @@ JNIEXPORT jfloatArray JNICALL Java_com_baidu_paddle_PML_predictYuv( JNIEXPORT jfloatArray JNICALL Java_com_baidu_paddle_PML_predict(JNIEnv *env, jclass thiz, jfloatArray buf); +/** + * setThreadCount for multithread + */ +JNIEXPORT void JNICALL Java_com_baidu_paddle_PML_setThread(JNIEnv *env, + jclass thiz, + jint threadCount); /** * clear data of the net when destroy for android */ diff --git a/src/operators/conv_transpose_op.cpp b/src/operators/conv_transpose_op.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e1d9e9c519732607b27aac7873b6a8eec93510b --- /dev/null +++ b/src/operators/conv_transpose_op.cpp @@ -0,0 +1,23 @@ +/* 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 CONV_TRANSPOSE + +#include "operators/conv_transpose_op.h" + +namespace paddle_mobile { +namespace operators {} +} // namespace paddle_mobile + +#endif diff --git a/src/operators/conv_transpose_op.h b/src/operators/conv_transpose_op.h new file mode 100644 index 0000000000000000000000000000000000000000..8176913b0d9535f7bd677439f314137e9d59ad72 --- /dev/null +++ b/src/operators/conv_transpose_op.h @@ -0,0 +1,91 @@ +/* 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 CONV_TRANSPOSE + +#pragma once + +#include +#include + +#include "framework/operator.h" +#include "operators/kernel/conv_transpose_kernel.h" + +namespace paddle_mobile { +namespace operators { +template +class ConvOpTranspose : public framework::OperatorWithKernel< + DeviceType, ConvTransposeParam, + operators::ConvTransposeKernel> { + public: + ConvOpTranspose(const std::string &type, const VariableNameMap &inputs, + const VariableNameMap &outputs, + const framework::AttributeMap &attrs, + std::shared_ptr scope) + : framework::OperatorWithKernel< + DeviceType, ConvTransposeParam, + operators::ConvTransposeKernel>( + type, inputs, outputs, attrs, scope) {} + + void InferShape() const { + auto input = this->param_.Input(); + auto in_dims = input->dims(); + + auto filter = this->param_.Filter(); + auto filter_dims = filter->dims(); + + std::vector strides = this->param_.Strides(); + std::vector paddings = this->param_.Paddings(); + std::vector dilations = this->param_.Dilations(); + + int groups = this->param_.Groups(); + + PADDLE_MOBILE_ENFORCE( + in_dims.size() == 4 || in_dims.size() == 5, + "ConvTransposeOp intput should be 4-D or 5-D tensor."); + PADDLE_MOBILE_ENFORCE( + in_dims.size() == filter_dims.size(), + "ConvTransposeOp input dimension and filter dimension " + "should be the same."); + PADDLE_MOBILE_ENFORCE( + in_dims.size() - strides.size() == 2U, + "ConvTransposeOp input dimension and strides dimension should " + "be consistent."); + PADDLE_MOBILE_ENFORCE(paddings.size() == strides.size(), + "ConvTransposeOp paddings dimension and strides " + "dimension should be the same."); + PADDLE_MOBILE_ENFORCE(paddings.size() == dilations.size(), + "ConvTransposeOp paddings dimension and dilations " + "dimension should be the same."); + PADDLE_MOBILE_ENFORCE( + in_dims[1] == filter_dims[0], + "In ConvTransposeOp, The number of input channels should " + "be equal to the number of filter's channels."); + + std::vector output_shape({in_dims[0], filter_dims[1] * groups}); + for (size_t i = 0; i < strides.size(); ++i) { + auto filter_extent = dilations[i] * (filter_dims[i + 2] - 1) + 1; + output_shape.push_back((in_dims[i + 2] - 1) * strides[i] - + 2 * paddings[i] + filter_extent); + } + this->param_.Output()->Resize(framework::make_ddim(output_shape)); + } + + private: +}; + +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/src/operators/kernel/arm/conv_transpose_kernel.cpp b/src/operators/kernel/arm/conv_transpose_kernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d3c1aa96fd34207d401ef96058713d9b93098347 --- /dev/null +++ b/src/operators/kernel/arm/conv_transpose_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 CONV_TRANSPOSE + +#include "operators/kernel/conv_transpose_kernel.h" +#include "operators/kernel/central-arm-func/conv_transpose_arm_func.h" + +namespace paddle_mobile { +namespace operators { + +template <> +bool ConvTransposeKernel::Init(ConvTransposeParam *param) { + return true; +} + +template <> +void ConvTransposeKernel::Compute( + const ConvTransposeParam ¶m) const { + ConvTransposeCompute(param); +} + +template class ConvTransposeKernel; + +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/src/operators/kernel/central-arm-func/conv_transpose_arm_func.h b/src/operators/kernel/central-arm-func/conv_transpose_arm_func.h new file mode 100644 index 0000000000000000000000000000000000000000..8c120c60be79b51c2a2e4c8fbccf1d546871f839 --- /dev/null +++ b/src/operators/kernel/central-arm-func/conv_transpose_arm_func.h @@ -0,0 +1,114 @@ +/* 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 CONV_TRANSPOSE + +#include + +#include "framework/ddim.h" +#include "operators/math/im2col.h" +#include "operators/math/math_function.h" +#include "operators/math/vol2col.h" +#include "operators/op_param.h" + +#pragma once + +namespace paddle_mobile { +namespace operators { + +template +void ConvTransposeCompute(const ConvTransposeParam ¶m) { + const Tensor *input = param.Input(); + Tensor filter = *param.Filter(); + Tensor *output = param.Output(); + + auto strides = param.Strides(); + auto paddings = param.Paddings(); + auto dilations = param.Dilations(); + auto groups = param.Groups(); + + const int batch_size = input->dims()[0]; + + std::vector input_shape_vec = framework::vectorize(input->dims()); + std::vector filter_shape_vec = framework::vectorize(filter.dims()); + + size_t data_dim = filter_shape_vec.size() - 2; + + // 5 或者 7 + std::vector col_shape_vec(1 + 2 * data_dim); + + // output c / groups + col_shape_vec[0] = output->dims()[1] / groups; + for (size_t i = 0; i < data_dim; ++i) { + // filter shape filter h filter w + col_shape_vec[i + 1] = filter_shape_vec[i + 2]; + // input shape input h input w + col_shape_vec[i + 1 + data_dim] = input_shape_vec[i + 2]; + } + + framework::DDim col_shape(framework::make_ddim(col_shape_vec)); + framework::DDim col_matrix_shape = + framework::flatten_to_2d(col_shape, data_dim + 1); + + Tensor col; + col.mutable_data

(col_shape); + + Tensor col_matrix; + col_matrix.ShareDataWith(col); + col_matrix.Resize(col_matrix_shape); + + framework::DDim output_shape = + framework::slice_ddim(output->dims(), 1, output->dims().size()); + + framework::DDim input_matrix_shape = {input->dims()[1], col_matrix_shape[1]}; + + // filter size: (m, c/g * k_h * k_w) or (m, c/g * k_d * k_h * k_w) + framework::DDim filter_matrix_shape = {input->dims()[1], col_matrix_shape[0]}; + filter.Resize(filter_matrix_shape); + + output->mutable_data

(); + + int in_step = static_cast(input->dims()[1]) / groups; + int out_step = static_cast(output->dims()[1]) / groups; + + math::Col2ImFunctor col2im; + math::Col2VolFunctor col2vol; + + for (int i = 0; i < batch_size; ++i) { + Tensor input_batch = input->Slice(i, i + 1).Resize(input_matrix_shape); + Tensor output_batch = output->Slice(i, i + 1).Resize(output_shape); + + for (int g = 0; g < groups; ++g) { + Tensor in_slice = input_batch.Slice(g * in_step, (g + 1) * in_step); + Tensor filter_slice = filter.Slice(g * in_step, (g + 1) * in_step); + Tensor out_slice = output_batch.Slice(g * out_step, (g + 1) * out_step); + + math::matmul(filter_slice, true, in_slice, false, static_cast

(1.0), + &col_matrix, static_cast

(0.0)); + if (data_dim == 2U) { + col2im(col, dilations, strides, + std::vector{paddings[0], paddings[1], paddings[0], + paddings[1]}, + &out_slice); + + } else if (data_dim == 3U) { + col2vol(col, dilations, strides, paddings, &out_slice); + } + } + } +} + +} // namespace operators +} // namespace paddle_mobile +#endif diff --git a/src/operators/kernel/conv_transpose_kernel.h b/src/operators/kernel/conv_transpose_kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..bb9751d2462e0f338c8fe90d3de8020c133722e6 --- /dev/null +++ b/src/operators/kernel/conv_transpose_kernel.h @@ -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 CONV_TRANSPOSE + +#pragma once + +#include "framework/operator.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +using framework::OpKernelBase; + +template +class ConvTransposeKernel + : public OpKernelBase { + public: + void Compute(const ConvTransposeParam ¶m) const; + + bool Init(ConvTransposeParam *param); +}; + +} // namespace operators +} // namespace paddle_mobile + +#endif // PADDLE_MOBILE_DE_CONV_KERNEL_H diff --git a/src/operators/op_param.h b/src/operators/op_param.h index 844d2f1068b7499bef35a7fd346317c1c3f6ad65..237b8ea5ba58f5705eec9d0a8c3a8f0c781a4ada 100644 --- a/src/operators/op_param.h +++ b/src/operators/op_param.h @@ -1419,5 +1419,45 @@ class DropoutParam : public OpParam { }; #endif +#ifdef CONV_TRANSPOSE +class ConvTransposeParam : public OpParam { + public: + ConvTransposeParam(const VariableNameMap &inputs, + const VariableNameMap &outputs, const AttributeMap &attrs, + const Scope &scope) { + filter_ = FilterFrom(inputs, scope); + input_ = InputFrom(inputs, scope); + output_ = OutputFrom(outputs, scope); + strides_ = GetAttr>("strides", attrs); + paddings_ = GetAttr>("paddings", attrs); + dilations_ = GetAttr>("dilations", attrs); + groups = GetAttr("groups", attrs); + } + + const Tensor *Input() const { return input_; } + + const Tensor *Filter() const { return filter_; } + + Tensor *Output() const { return output_; } + + const vector &Strides() const { return strides_; } + + const vector &Paddings() const { return paddings_; } + + const vector &Dilations() const { return dilations_; } + + const int &Groups() const { return groups; } + + private: + Tensor *input_; + Tensor *output_; + Tensor *filter_; + vector strides_; + vector paddings_; + vector dilations_; + int groups; +}; +#endif + } // namespace operators } // namespace paddle_mobile diff --git a/tools/op.cmake b/tools/op.cmake index 361381b81a603274207e50aeb8f0feddcff4e2ed..6b6cb13dbc49b2a6cd672ea4e637f6650d60f8d2 100644 --- a/tools/op.cmake +++ b/tools/op.cmake @@ -90,6 +90,7 @@ endif() if(NOT FOUND_MATCH) message("--default--") set(BATCHNORM_OP ON) + set(CONV_TRANSPOSE_OP ON) set(BOXCODER_OP ON) set(CONCAT_OP ON) set(CONV_OP ON) @@ -243,3 +244,6 @@ if (REGION_OP) add_definitions(-DREGION_OP) endif() +if (CONV_TRANSPOSE_OP) + add_definitions(-DCONV_TRANSPOSE) +endif()