Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C-API for inference. #1062

Merged
merged 57 commits into from
Apr 21, 2017
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
fbb1b0e
Start Doing C-API for predict.
reyoung Jan 3, 2017
aa6e252
Doing C-API
reyoung Jan 4, 2017
3fcd81f
Stash
reyoung Jan 5, 2017
a873a40
Try to use standard way to import gflags.
reyoung Jan 5, 2017
106620e
Merge branch 'feature/use_std_cmake' into feature/c_api
reyoung Jan 5, 2017
fdb64ac
add unittest for prediction
reyoung Jan 5, 2017
a22c889
Merge branch 'develop' of github.com:baidu/Paddle into feature/c_api
reyoung Jan 10, 2017
657d204
Merge branch 'feature/add_third_party_for_gflags' into feature/c_api
reyoung Jan 10, 2017
873368f
Add style check to target
reyoung Jan 10, 2017
fe8d5ff
Add WITH_C_API option
reyoung Jan 10, 2017
d23bae7
Merge branch 'develop' of github.com:baidu/Paddle into feature/c_api
reyoung Jan 11, 2017
06b1a6a
Fix unittest
reyoung Jan 11, 2017
4fd6888
C-API for model inference.
reyoung Jan 11, 2017
005ac1f
Add warning message
reyoung Jan 11, 2017
3bc0d8b
Revert unchanged files
reyoung Jan 11, 2017
987a908
Fix a bug, should be ALL in custom_target
reyoung Jan 12, 2017
3b5bed6
Add dump binary config
reyoung Jan 12, 2017
0874a7e
Fix typo in API.h
reyoung Jan 12, 2017
6243853
Add comments.
reyoung Jan 12, 2017
6402214
Fix unittest
reyoung Jan 13, 2017
88c3862
Merge branch 'develop' of github.com:baidu/Paddle into feature/c_api
reyoung Jan 19, 2017
30a6f9b
Start doing shared c_api library
reyoung Jan 19, 2017
510ccfe
Make Paddle exports the symbols
reyoung Jan 19, 2017
4380e73
Merge branch 'develop' of github.com:baidu/Paddle into feature/c_api
reyoung Mar 6, 2017
8a1e32d
Fix compile error.
reyoung Mar 7, 2017
c32ade7
Add todo
reyoung Mar 7, 2017
97c6425
Add some more interfaces
reyoung Mar 7, 2017
3519c63
complete some functions of c-api.
Mar 9, 2017
8feb583
Merge branch 'feature/fix_ccache_not_in_path' into feature/c_api
reyoung Mar 9, 2017
d34322e
Merge branch 'develop' of github.com:baidu/Paddle into feature/c_api
reyoung Mar 9, 2017
5a9987a
Fix bugs in lizhao's code
reyoung Mar 9, 2017
7bb12fd
Refactor API follow comments.
reyoung Mar 10, 2017
5ac9c22
Install shared lib
reyoung Mar 10, 2017
08113b2
Merge branch 'develop' of github.com:baidu/Paddle into feature/c_api
reyoung Mar 20, 2017
b528828
Rename some API to C-Style
reyoung Mar 21, 2017
0afd5c3
Stash
reyoung Mar 21, 2017
c5eac0a
Rename API
reyoung Mar 24, 2017
58e5b87
Add license
reyoung Mar 24, 2017
d49c627
GNU Style API
reyoung Mar 24, 2017
9c1c19b
Merge branch 'develop' of github.com:baidu/Paddle into feature/c_api
reyoung Mar 24, 2017
470bbcf
Add example
reyoung Mar 24, 2017
34b3ee3
Add sequence exampleAdd sequence exampleAdd sequence exampleAdd sequence
reyoung Mar 26, 2017
852a94f
Add model_inference directory
reyoung Mar 26, 2017
0d73f4c
Add usage documentation of C-API.
reyoung Mar 26, 2017
6b78a11
Merge branch 'develop' of github.com:baidu/Paddle into feature/c_api
reyoung Mar 26, 2017
6623096
Add Implementation documentation.
reyoung Mar 26, 2017
505d207
Add toc
reyoung Mar 26, 2017
e7bc880
Revert unchanged file.
reyoung Mar 26, 2017
ddbb610
Find a bug about recommark.
reyoung Mar 27, 2017
18a3588
Merge branch 'develop' of github.com:baidu/Paddle into feature/c_api
reyoung Apr 14, 2017
87dfc12
Follow comments
reyoung Apr 14, 2017
bda2008
Add TODO for GPU unittest
reyoung Apr 14, 2017
28c4cee
Merge branch 'develop' of github.com:baidu/Paddle into feature/c_api
reyoung Apr 19, 2017
91927cc
Change name conventions.
reyoung Apr 20, 2017
d6a7648
Merge branch 'develop' of github.com:baidu/Paddle into feature/c_api
reyoung Apr 20, 2017
dfd79c8
Follow comments.
reyoung Apr 20, 2017
4e0f72e
Typo
reyoung Apr 21, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ option(WITH_DOC "Compile PaddlePaddle with documentation" OFF)
option(ON_COVERALLS "Compile PaddlePaddle with code coverage" OFF)
option(COVERALLS_UPLOAD "Package code coverage data to coveralls" OFF)
option(ON_TRAVIS "Exclude special unit test on Travis CI" OFF)
option(WITH_C_API "Compile PaddlePaddle with C-API(Prediction)" OFF)

# CMAKE_BUILD_TYPE
if(NOT CMAKE_BUILD_TYPE)
Expand All @@ -53,6 +54,13 @@ endif()

set(THIRD_PARTY_PATH "${PROJ_ROOT}/third_party" CACHE STRING
"A path setting third party libraries download & build directories.")

if (WITH_C_API AND WITH_PYTHON)
message(WARNING "It is suggest not embedded a python interpreter in Paddle "
"when using C-API. It will give an unpredictable behavior when using a "
"different Python interpreter from compiling.")
endif()

########################################################################################

include(external/zlib) # download, build, install zlib
Expand Down
582 changes: 0 additions & 582 deletions cmake/FindGflags.cmake

This file was deleted.

1 change: 1 addition & 0 deletions cmake/flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,4 @@ if(CUDA_ARCH)
endif()

set(CUDA_NVCC_FLAGS ${__arch_flags} ${CUDA_NVCC_FLAGS})

4 changes: 3 additions & 1 deletion paddle/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ add_subdirectory(gserver)
add_subdirectory(pserver)
add_subdirectory(trainer)
add_subdirectory(scripts)

if(WITH_C_API)
add_subdirectory(capi)
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in
${CMAKE_CURRENT_SOURCE_DIR}/setup.py)

Expand Down
75 changes: 75 additions & 0 deletions paddle/capi/Arguments.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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 "PaddleCAPI.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

看到大家都把这个目录叫做 "c", 这个作为参考

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/dmlc/mxnet/tree/master/src/c_api

一般项目目录第一层是编码语言,就比如Paddle

-- paddle
 |- python
 |- proto

所以有一些项目的会把这部分放到c目录下。而对于Paddle,一来C/CPP区分界限不明显,二来但就这个C-API来说,本身也是C与C++的混合写法。所以很难独立成C目录。

#include "PaddleCAPIPrivate.h"

using paddle::capi::cast;

#define castArg(v) cast<paddle::capi::CArguments>(v)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

上文提到的,castArg时,是否需要检查type是不是kARGUMENTS

#define castIVec(v) cast<paddle::capi::CIVector>(v)

extern "C" {
int PDArgsCreateNone(PD_Arguments* args) {
auto ptr = new paddle::capi::CArguments();
*args = ptr;
return kPD_NO_ERROR;
}

int PDArgsDestroy(PD_Arguments args) {
if (args == nullptr) return kPD_NULLPTR;
delete castArg(args);
return kPD_NO_ERROR;
}

int PDArgsGetSize(PD_Arguments args, uint64_t* size) {
if (args == nullptr || size == nullptr) return kPD_NULLPTR;
*size = castArg(args)->args.size();
return kPD_NO_ERROR;
}

int PDArgsResize(PD_Arguments args, uint64_t size) {
if (args == nullptr) return kPD_NULLPTR;
castArg(args)->args.resize(size);
return kPD_NO_ERROR;
}

int PDArgsSetValue(PD_Arguments args, uint64_t ID, PD_Matrix mat) {
if (args == nullptr || mat == nullptr) return kPD_NULLPTR;
auto m = paddle::capi::cast<paddle::capi::CMatrix>(mat);
if (m->mat == nullptr) return kPD_NULLPTR;
auto a = castArg(args);
if (ID >= a->args.size()) return kPD_OUT_OF_RANGE;
a->args[ID].value = m->mat;
return kPD_NO_ERROR;
}

int PDArgsGetValue(PD_Arguments args, uint64_t ID, PD_Matrix mat) {
if (args == nullptr || mat == nullptr) return kPD_NULLPTR;
auto m = paddle::capi::cast<paddle::capi::CMatrix>(mat);
auto a = castArg(args);
if (ID >= a->args.size()) return kPD_OUT_OF_RANGE;
m->mat = a->args[ID].value;
return kPD_NO_ERROR;
}

int PDArgsGetIds(PD_Arguments args, uint64_t ID, PD_IVector ids) {
if (args == nullptr || ids == nullptr) return kPD_NULLPTR;
auto iv = castIVec(ids);
auto a = castArg(args);
if (ID >= a->args.size()) return kPD_OUT_OF_RANGE;
iv->vec = a->args[ID].ids;
return kPD_NO_ERROR;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

目前还不支持sparse与sequence数据

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是的,这个预测目前只支持Dense输入输出的预测。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arguments希望添加一个设置frameWidthframeHeight的接口,以支持使用变长图像数据的模型。
另外,如果使用maxid_layer作为输出,最终labels存在ids里面,对应的概率存在in里面,要不要增加一个获取in的接口,还是改paddle的core代码?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

先checkin这个版本吧。。

75 changes: 75 additions & 0 deletions paddle/capi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
if (WITH_DOUBLE)
set(PADDLE_FLOAT_TYPE double)
else ()
set(PADDLE_FLOAT_TYPE float)
endif()

# config.h used for C-API. It will store Paddle building configuration as a
# header. Make user just include PaddleCAPI.h then can get building
# configuration without explicitly set -DPADDLE_WITH_DOUBLE when building their
# libraries.
configure_file(config.h.in config.h @ONLY)

# PaddleCAPI.h is the only header we exposed. It currently only used for model
# inference.
set(CAPI_HEADER PaddleCAPI.h)


set(CAPI_PRIVATE_HEADER PaddleCAPIPrivate.h)
file(GLOB CAPI_SOURCES *.cpp)

# building paddle_capi
add_library(paddle_capi STATIC ${CAPI_SOURCES})

target_include_directories(paddle_capi PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

add_style_check_target(paddle_capi ${CAPI_SOURCES} ${CAPI_HEADER}
${CAPI_PRIVATE_HEADER})

add_dependencies(paddle_capi gen_proto_cpp)


# combine all paddle static libraries together, into libpaddle_capi_whole.a
# user should use PaddleCAPI as -lpaddle_capi_whole
set(capi_whole_library libpaddle_capi_whole.a)
add_custom_target(paddle_capi_whole ALL
COMMAND mkdir -p o_files/capi && cd o_files/capi/ && ar -x $<TARGET_FILE:paddle_capi>
COMMAND mkdir -p o_files/utils && cd o_files/utils/ && ar -x $<TARGET_FILE:paddle_utils>
COMMAND mkdir -p o_files/parameter && cd o_files/parameter/ && ar -x $<TARGET_FILE:paddle_parameter>
COMMAND mkdir -p o_files/math && cd o_files/math/ && ar -x $<TARGET_FILE:paddle_math>
COMMAND mkdir -p o_files/cuda && cd o_files/cuda/ && ar -x $<TARGET_FILE:paddle_cuda>
COMMAND mkdir -p o_files/function && cd o_files/function/ && ar -x $<TARGET_FILE:paddle_function>
COMMAND mkdir -p o_files/gserver && cd o_files/gserver/ && ar -x $<TARGET_FILE:paddle_gserver>
COMMAND mkdir -p o_files/proto && cd o_files/proto/ && ar -x $<TARGET_FILE:paddle_proto>
COMMAND mkdir -p o_files/network && cd o_files/network/ && ar -x
+$<TARGET_FILE:paddle_network>
+ COMMAND mkdir -p o_files/pserver && cd o_files/pserver/ && ar -x
+$<TARGET_FILE:paddle_pserver
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里应该是笔误吧,这个+号是应该删除的

COMMAND mkdir -p o_files/network && cd o_files/network/ && ar -x $<TARGET_FILE:paddle_network>
COMMAND mkdir -p o_files/pserver && cd o_files/pserver/ && ar -x $<TARGET_FILE:paddle_pserver>

COMMAND ar crs ${capi_whole_library} `find ./o_files -name '*.o'`
COMMAND rm -rf o_files
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS paddle_capi paddle_utils paddle_parameter paddle_math
paddle_cuda paddle_function paddle_gserver
paddle_proto paddle_pserver paddle_network
)
set_target_properties(paddle_capi_whole
PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${capi_whole_library})

add_library(paddle_capi_shared SHARED ${CAPI_SOURCES})
target_include_directories(paddle_capi_shared PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
link_paddle_exe(paddle_capi_shared)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

有个疑问,这个PR目前是只支持inference的吧,后面还会支持train?train会编译成另外一个库?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

train也会放到一个库里。


# install library & headers.
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${capi_whole_library} DESTINATION lib)
install(FILES ${CAPI_HEADER} DESTINATION include/paddle)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/config.h DESTINATION include/paddle)


# this variable used for unittest
set(PADDLE_CAPI_INC_PATH
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})

if (WITH_TESTING)
add_subdirectory(tests)
endif()
115 changes: 115 additions & 0 deletions paddle/capi/GradientMachine.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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 "PaddleCAPI.h"
#include "PaddleCAPIPrivate.h"
#include "paddle/gserver/gradientmachines/NeuralNetwork.h"

#define cast(v) paddle::capi::cast<paddle::capi::CGradientMachine>(v)

enum GradientMatchineCreateMode {
CREATE_MODE_NORMAL = 0,
CREATE_MODE_TESTING = 4
};

namespace paddle {

class MyNeuralNetwork : public NeuralNetwork {
public:
MyNeuralNetwork(const std::string& name, NeuralNetwork* network)
: NeuralNetwork(name, network) {}
};

NeuralNetwork* newCustomNerualNetwork(const std::string& name,
NeuralNetwork* network) {
return new MyNeuralNetwork(name, network);
}
} // namespace paddle

extern "C" {
int PDGradientMachineCreateForPredict(PD_GradientMachine* machine,
void* modelConfigProtobuf,
int size) {
if (modelConfigProtobuf == nullptr) return kPD_NULLPTR;
paddle::ModelConfig config;
if (!config.ParseFromArray(modelConfigProtobuf, size) ||
!config.IsInitialized()) {
return kPD_PROTOBUF_ERROR;
}

auto ptr = new paddle::capi::CGradientMachine();
ptr->machine.reset(paddle::GradientMachine::create(
config, CREATE_MODE_TESTING, {paddle::PARAMETER_VALUE}));
*machine = ptr;
return kPD_NO_ERROR;
}

int PDGradientMachineDestroy(PD_GradientMachine machine) {
delete cast(machine);
return kPD_NO_ERROR;
}

int PDGradientMachineLoadParameterFromDisk(PD_GradientMachine machine,
const char* path) {
auto m = cast(machine);
if (m == nullptr || path == nullptr || m->machine == nullptr)
return kPD_NULLPTR;
m->machine->loadParameters(path);
return kPD_NO_ERROR;
}

int PDGradientMachineForward(PD_GradientMachine machine,
PD_Arguments inArgs,
PD_Arguments outArgs,
bool isTrain) {
auto m = cast(machine);
auto in = paddle::capi::cast<paddle::capi::CArguments>(inArgs);
auto out = paddle::capi::cast<paddle::capi::CArguments>(outArgs);
if (m == nullptr || in == nullptr || out == nullptr || m->machine == nullptr)
return kPD_NULLPTR;
m->machine->forward(
in->args, &out->args, isTrain ? paddle::PASS_TRAIN : paddle::PASS_TEST);
return kPD_NO_ERROR;
}

int PDGradientMachineCreateSharedParam(PD_GradientMachine origin,
void* modelConfigProtobuf,
int size,
PD_GradientMachine* slave) {
auto o = cast(origin);
if (origin == nullptr || slave == nullptr || o->machine == nullptr) {
return kPD_NULLPTR;
}
paddle::ModelConfig config;
if (!config.ParseFromArray(modelConfigProtobuf, size) ||
!config.IsInitialized()) {
return kPD_PROTOBUF_ERROR;
}

std::unique_ptr<paddle::capi::CGradientMachine> ptr(
new paddle::capi::CGradientMachine());
auto nn = paddle::NeuralNetwork::create(config);
nn->init(config,
[&o](int paramId, paddle::Parameter* param) {
auto p = o->machine->getParameters()[paramId];
param->enableSharedType(paddle::PARAMETER_VALUE,
p->getBuf(paddle::PARAMETER_VALUE));
},
{paddle::PARAMETER_VALUE},
false);
ptr->machine.reset(nn);
*slave = ptr.release();
return kPD_NO_ERROR;
}
}
43 changes: 43 additions & 0 deletions paddle/capi/Main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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 <fenv.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include "PaddleCAPI.h"
#include "PaddleCAPIPrivate.h"
#include "paddle/trainer/TrainerConfigHelper.h"
#include "paddle/utils/Excepts.h"
#include "paddle/utils/PythonUtil.h"

static void initPaddle(int argc, char** argv) {
paddle::initMain(argc, argv);
paddle::initPython(argc, argv);
feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
}

extern "C" {
int PDInit(int argc, char** argv) {
std::vector<char*> realArgv;
realArgv.reserve(argc + 1);
realArgv.push_back(strdup(""));
for (int i = 0; i < argc; ++i) {
realArgv.push_back(argv[i]);
}
initPaddle(argc + 1, realArgv.data());
free(realArgv[0]);
return kPD_NO_ERROR;
}
}
Loading