Merge pull request #1062 from reyoung/feature/c_api
C-API for inference.feature/design_of_v2_layer_converter
commit
f979b126c1
@ -0,0 +1,117 @@
|
||||
/* 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 "arguments.h"
|
||||
#include "capi_private.h"
|
||||
|
||||
using paddle::capi::cast;
|
||||
|
||||
#define castArg(v) cast<paddle::capi::CArguments>(v)
|
||||
#define castIVec(v) cast<paddle::capi::CIVector>(v)
|
||||
|
||||
extern "C" {
|
||||
paddle_arguments paddle_arguments_create_none() {
|
||||
return new paddle::capi::CArguments();
|
||||
}
|
||||
|
||||
paddle_error paddle_arguments_destroy(paddle_arguments args) {
|
||||
if (args == nullptr) return kPD_NULLPTR;
|
||||
delete castArg(args);
|
||||
return kPD_NO_ERROR;
|
||||
}
|
||||
|
||||
paddle_error paddle_arguments_get_size(paddle_arguments args, uint64_t* size) {
|
||||
if (args == nullptr || size == nullptr) return kPD_NULLPTR;
|
||||
*size = castArg(args)->args.size();
|
||||
return kPD_NO_ERROR;
|
||||
}
|
||||
|
||||
paddle_error paddle_arguments_resize(paddle_arguments args, uint64_t size) {
|
||||
if (args == nullptr) return kPD_NULLPTR;
|
||||
castArg(args)->args.resize(size);
|
||||
return kPD_NO_ERROR;
|
||||
}
|
||||
|
||||
paddle_error paddle_arguments_set_value(paddle_arguments args,
|
||||
uint64_t ID,
|
||||
paddle_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;
|
||||
}
|
||||
|
||||
paddle_error paddle_arguments_get_value(paddle_arguments args,
|
||||
uint64_t ID,
|
||||
paddle_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;
|
||||
}
|
||||
|
||||
paddle_error paddle_arguments_get_ids(paddle_arguments args,
|
||||
uint64_t ID,
|
||||
paddle_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;
|
||||
}
|
||||
|
||||
paddle_error paddle_arguments_set_ids(paddle_arguments args,
|
||||
uint64_t ID,
|
||||
paddle_ivector ids) {
|
||||
//! TODO(lizhao): Complete this method.
|
||||
if (args == nullptr || ids == nullptr) return kPD_NULLPTR;
|
||||
auto iv = paddle::capi::cast<paddle::capi::CIVector>(ids);
|
||||
if (iv->vec == nullptr) return kPD_NULLPTR;
|
||||
auto a = castArg(args);
|
||||
if (ID >= a->args.size()) return kPD_OUT_OF_RANGE;
|
||||
a->args[ID].ids = iv->vec;
|
||||
return kPD_NO_ERROR;
|
||||
}
|
||||
|
||||
paddle_error paddle_arguments_set_sequence_start_pos(paddle_arguments args,
|
||||
uint64_t ID,
|
||||
uint32_t nestedLevel,
|
||||
paddle_ivector seqPos) {
|
||||
if (args == nullptr || seqPos == nullptr) return kPD_NULLPTR;
|
||||
auto iv = paddle::capi::cast<paddle::capi::CIVector>(seqPos);
|
||||
if (iv->vec == nullptr) return kPD_NULLPTR;
|
||||
auto a = castArg(args);
|
||||
return a->accessSeqPos(ID, nestedLevel, [&iv](paddle::ICpuGpuVectorPtr& ptr) {
|
||||
ptr = std::make_shared<paddle::ICpuGpuVector>(iv->vec);
|
||||
});
|
||||
}
|
||||
|
||||
paddle_error paddle_arguments_get_sequence_start_pos(paddle_arguments args,
|
||||
uint64_t ID,
|
||||
uint32_t nestedLevel,
|
||||
paddle_ivector seqPos) {
|
||||
if (args == nullptr || seqPos == nullptr) return kPD_NULLPTR;
|
||||
auto iv = paddle::capi::cast<paddle::capi::CIVector>(seqPos);
|
||||
auto a = castArg(args);
|
||||
return a->accessSeqPos(ID, nestedLevel, [&iv](paddle::ICpuGpuVectorPtr& ptr) {
|
||||
iv->vec = ptr->getMutableVector(false);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
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.
|
||||
file(GLOB CAPI_HEADERS *.h)
|
||||
set(CAPI_PRIVATE_HEADER capi_private.h)
|
||||
list(REMOVE_ITEM CAPI_HEADERS ${CAPI_PRIVATE_HEADER})
|
||||
file(GLOB CAPI_SOURCES *.cpp)
|
||||
|
||||
# building paddle_capi
|
||||
add_library(paddle_capi STATIC ${CAPI_HEADERS} ${CAPI_PRIVATE_HEADER}
|
||||
${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>
|
||||
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)
|
||||
|
||||
# install library & headers.
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${capi_whole_library} DESTINATION lib)
|
||||
install(FILES ${CAPI_HEADERS} DESTINATION include/paddle)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/config.h DESTINATION include/paddle)
|
||||
install(TARGETS paddle_capi_shared DESTINATION lib)
|
||||
|
||||
# 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()
|
@ -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 "capi_private.h"
|
||||
#include "main.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" {
|
||||
paddle_error paddle_init(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;
|
||||
}
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
/* 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 "capi_private.h"
|
||||
#include "hl_cuda.h"
|
||||
#include "matrix.h"
|
||||
|
||||
#define cast(v) paddle::capi::cast<paddle::capi::CMatrix>(v)
|
||||
extern "C" {
|
||||
paddle_matrix paddle_matrix_create(uint64_t height,
|
||||
uint64_t width,
|
||||
bool useGpu) {
|
||||
auto ptr = new paddle::capi::CMatrix();
|
||||
ptr->mat = paddle::Matrix::create(height, width, false, useGpu);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
paddle_matrix paddle_matrix_create_none() {
|
||||
return new paddle::capi::CMatrix();
|
||||
}
|
||||
|
||||
paddle_error paddle_matrix_destroy(paddle_matrix mat) {
|
||||
if (mat == nullptr) return kPD_NULLPTR;
|
||||
auto ptr = cast(mat);
|
||||
delete ptr;
|
||||
return kPD_NO_ERROR;
|
||||
}
|
||||
|
||||
paddle_error paddle_matrix_set_row(paddle_matrix mat,
|
||||
uint64_t rowID,
|
||||
paddle_real* rowArray) {
|
||||
if (mat == nullptr) return kPD_NULLPTR;
|
||||
auto ptr = cast(mat);
|
||||
if (ptr->mat == nullptr) return kPD_NULLPTR;
|
||||
if (rowID >= ptr->mat->getHeight()) return kPD_OUT_OF_RANGE;
|
||||
paddle::real* buf = ptr->mat->getRowBuf(rowID);
|
||||
size_t width = ptr->mat->getWidth();
|
||||
#ifndef PADDLE_ONLY_CPU
|
||||
hl_memcpy(buf, rowArray, sizeof(paddle::real) * width);
|
||||
#else
|
||||
std::copy(rowArray, rowArray + width, buf);
|
||||
#endif
|
||||
return kPD_NO_ERROR;
|
||||
}
|
||||
|
||||
paddle_error paddle_matrix_get_row(paddle_matrix mat,
|
||||
uint64_t rowID,
|
||||
paddle_real** rawRowBuffer) {
|
||||
if (mat == nullptr) return kPD_NULLPTR;
|
||||
auto ptr = cast(mat);
|
||||
if (ptr->mat == nullptr) return kPD_NULLPTR;
|
||||
if (rowID >= ptr->mat->getHeight()) return kPD_OUT_OF_RANGE;
|
||||
*rawRowBuffer = ptr->mat->getRowBuf(rowID);
|
||||
return kPD_NO_ERROR;
|
||||
}
|
||||
|
||||
paddle_error paddle_matrix_get_shape(paddle_matrix mat,
|
||||
uint64_t* height,
|
||||
uint64_t* width) {
|
||||
if (mat == nullptr) return kPD_NULLPTR;
|
||||
if (height != nullptr) {
|
||||
*height = cast(mat)->mat->getHeight();
|
||||
}
|
||||
if (width != nullptr) {
|
||||
*width = cast(mat)->mat->getWidth();
|
||||
}
|
||||
return kPD_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
paddle_matrix paddle_matrix_create_sparse(
|
||||
uint64_t height, uint64_t width, uint64_t nnz, bool isBinary, bool useGpu) {
|
||||
auto ptr = new paddle::capi::CMatrix();
|
||||
ptr->mat = paddle::Matrix::createSparseMatrix(
|
||||
height,
|
||||
width,
|
||||
nnz,
|
||||
isBinary ? paddle::NO_VALUE : paddle::FLOAT_VALUE,
|
||||
paddle::SPARSE_CSR,
|
||||
false,
|
||||
useGpu);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
paddle_error paddle_matrix_sparse_copy_from(paddle_matrix mat,
|
||||
int* rowArray,
|
||||
uint64_t rowSize,
|
||||
int* colArray,
|
||||
uint64_t colSize,
|
||||
float* valueArray,
|
||||
uint64_t valueSize) {
|
||||
if (mat == nullptr) return kPD_NULLPTR;
|
||||
auto ptr = cast(mat);
|
||||
if (rowArray == nullptr || colArray == nullptr ||
|
||||
(valueSize != 0 && valueArray == nullptr) || ptr->mat == nullptr) {
|
||||
return kPD_NULLPTR;
|
||||
}
|
||||
if (auto sparseMat = dynamic_cast<paddle::CpuSparseMatrix*>(ptr->mat.get())) {
|
||||
std::vector<int> row(rowSize);
|
||||
row.assign(rowArray, rowArray + rowSize);
|
||||
std::vector<int> col(colSize);
|
||||
col.assign(colArray, colArray + colSize);
|
||||
std::vector<paddle_real> val(valueSize);
|
||||
if (valueSize) {
|
||||
val.assign(valueArray, valueArray + valueSize);
|
||||
}
|
||||
sparseMat->copyFrom(row, col, val);
|
||||
return kPD_NO_ERROR;
|
||||
} else {
|
||||
return kPD_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/* 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 "capi_private.h"
|
||||
#include "vector.h"
|
||||
|
||||
using paddle::capi::cast;
|
||||
|
||||
extern "C" {
|
||||
|
||||
paddle_ivector paddle_ivector_create_none() {
|
||||
return new paddle::capi::CIVector();
|
||||
}
|
||||
|
||||
paddle_ivector paddle_ivector_create(int* array,
|
||||
uint64_t size,
|
||||
bool copy,
|
||||
bool useGPU) {
|
||||
auto ptr = new paddle::capi::CIVector();
|
||||
if (copy) {
|
||||
ptr->vec = paddle::IVector::create(size, useGPU);
|
||||
ptr->vec->copyFrom(array, size);
|
||||
} else {
|
||||
ptr->vec = paddle::IVector::create(array, size, useGPU);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
paddle_error paddle_ivector_destroy(paddle_ivector ivec) {
|
||||
if (ivec == nullptr) return kPD_NULLPTR;
|
||||
delete cast<paddle::capi::CIVector>(ivec);
|
||||
return kPD_NO_ERROR;
|
||||
}
|
||||
|
||||
paddle_error paddle_ivector_get(paddle_ivector ivec, int** buffer) {
|
||||
if (ivec == nullptr || buffer == nullptr) return kPD_NULLPTR;
|
||||
auto v = cast<paddle::capi::CIVector>(ivec);
|
||||
if (v->vec == nullptr) return kPD_NULLPTR;
|
||||
*buffer = v->vec->getData();
|
||||
return kPD_NO_ERROR;
|
||||
}
|
||||
|
||||
paddle_error paddle_ivector_resize(paddle_ivector ivec, uint64_t size) {
|
||||
if (ivec == nullptr) return kPD_NULLPTR;
|
||||
auto v = cast<paddle::capi::CIVector>(ivec);
|
||||
if (v->vec == nullptr) return kPD_NULLPTR;
|
||||
v->vec->resize(size);
|
||||
return kPD_NO_ERROR;
|
||||
}
|
||||
|
||||
paddle_error paddle_ivector_get_size(paddle_ivector ivec, uint64_t* size) {
|
||||
if (ivec == nullptr) return kPD_NULLPTR;
|
||||
auto v = cast<paddle::capi::CIVector>(ivec);
|
||||
if (v->vec == nullptr) return kPD_NULLPTR;
|
||||
*size = v->vec->getSize();
|
||||
return kPD_NO_ERROR;
|
||||
}
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
/* 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. */
|
||||
|
||||
#ifndef __PADDLE_CAPI_ARGUMENTS_H__
|
||||
#define __PADDLE_CAPI_ARGUMENTS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "config.h"
|
||||
#include "error.h"
|
||||
#include "matrix.h"
|
||||
#include "vector.h"
|
||||
|
||||
/**
|
||||
* Arguments functions. Each argument means layer output. Arguments means a
|
||||
* array of arguemnt.
|
||||
*/
|
||||
typedef void* paddle_arguments;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief paddle_arguments_create_none Create a array of arguments, which size
|
||||
* is zero.
|
||||
* @return Arguemnts
|
||||
*/
|
||||
PD_API paddle_arguments paddle_arguments_create_none();
|
||||
|
||||
/**
|
||||
* @brief paddle_arguments_destroy Destroy the arguments
|
||||
* @param args arguments to destroy
|
||||
* @return paddle_error
|
||||
*/
|
||||
PD_API paddle_error paddle_arguments_destroy(paddle_arguments args);
|
||||
|
||||
/**
|
||||
* @brief paddle_arguments_get_size Get size of arguments array
|
||||
* @param [in] args arguments array
|
||||
* @param [out] size array size
|
||||
* @return paddle_error
|
||||
*/
|
||||
PD_API paddle_error paddle_arguments_get_size(paddle_arguments args,
|
||||
uint64_t* size);
|
||||
|
||||
/**
|
||||
* @brief PDArgsResize Resize a arguments array.
|
||||
* @param args arguments array.
|
||||
* @param size target size of array
|
||||
* @return paddle_error
|
||||
*/
|
||||
PD_API paddle_error paddle_arguments_resize(paddle_arguments args,
|
||||
uint64_t size);
|
||||
|
||||
/**
|
||||
* @brief PDArgsSetValue Set value matrix of one argument in array, which index
|
||||
* is `ID`.
|
||||
* @param args arguments array
|
||||
* @param ID array index
|
||||
* @param mat matrix pointer
|
||||
* @return paddle_error
|
||||
*/
|
||||
PD_API paddle_error paddle_arguments_set_value(paddle_arguments args,
|
||||
uint64_t ID,
|
||||
paddle_matrix mat);
|
||||
|
||||
/**
|
||||
* @brief PDArgsGetValue Get value matrix of one argument in array, which index
|
||||
* is `ID`.
|
||||
* @param [in] args arguments array
|
||||
* @param [in] ID array index
|
||||
* @param [out] mat matrix pointer
|
||||
* @return paddle_error
|
||||
*/
|
||||
PD_API paddle_error paddle_arguments_get_value(paddle_arguments args,
|
||||
uint64_t ID,
|
||||
paddle_matrix mat);
|
||||
|
||||
/**
|
||||
* @brief PDArgsGetIds Get the integer vector of one argument in array, which
|
||||
* index is `ID`.
|
||||
* @param args arguments array
|
||||
* @param ID array index
|
||||
* @param ids integer vector pointer
|
||||
* @return paddle_error
|
||||
*/
|
||||
PD_API paddle_error paddle_arguments_get_ids(paddle_arguments args,
|
||||
uint64_t ID,
|
||||
paddle_ivector ids);
|
||||
|
||||
/**
|
||||
* @brief PDArgsSetIds Set the integer vector of one argument in array, which
|
||||
* index is `ID`.
|
||||
* @param [in] args arguments array
|
||||
* @param [in] ID array index
|
||||
* @param [out] ids integer vector pointer
|
||||
* @return paddle_error
|
||||
*/
|
||||
PD_API paddle_error paddle_arguments_set_ids(paddle_arguments args,
|
||||
uint64_t ID,
|
||||
paddle_ivector ids);
|
||||
|
||||
/**
|
||||
* @brief PDArgsSetSequenceStartPos Set sequence start position vector of one
|
||||
* argument in array, which index is `ID`.
|
||||
* @param args arguments array
|
||||
* @param ID array index
|
||||
* @param seqPos sequence position array.
|
||||
* @return paddle_error
|
||||
*/
|
||||
PD_API paddle_error
|
||||
paddle_arguments_set_sequence_start_pos(paddle_arguments args,
|
||||
uint64_t ID,
|
||||
uint32_t nestedLevel,
|
||||
paddle_ivector seqPos);
|
||||
/**
|
||||
* @brief PDArgsGetSequenceStartPos Get sequence start position vector of one
|
||||
* argument in array, which index is `ID`.
|
||||
* @param [in] args arguments array
|
||||
* @param [in] ID array index
|
||||
* @param [out] seqPos sequence position array
|
||||
* @return paddle_error
|
||||
*/
|
||||
PD_API paddle_error
|
||||
paddle_arguments_get_sequence_start_pos(paddle_arguments args,
|
||||
uint64_t ID,
|
||||
uint32_t nestedLevel,
|
||||
paddle_ivector seqPos);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,32 @@
|
||||
/* 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. */
|
||||
|
||||
#ifndef __PADDLE_CAPI_H__
|
||||
#define __PADDLE_CAPI_H__
|
||||
|
||||
/**
|
||||
* Paddle C API. It will replace SWIG as Multiple Language API for model
|
||||
* training & inference. Currently it is only used in model infernece.
|
||||
*
|
||||
* NOTE: This is an experimental API, it could be changed.
|
||||
*/
|
||||
#include "arguments.h"
|
||||
#include "config.h"
|
||||
#include "error.h"
|
||||
#include "gradient_machine.h"
|
||||
#include "main.h"
|
||||
#include "matrix.h"
|
||||
#include "vector.h"
|
||||
|
||||
#endif // PADDLECAPI_H_
|
@ -0,0 +1,82 @@
|
||||
/* 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 "capi.h"
|
||||
#include "paddle/gserver/gradientmachines/GradientMachine.h"
|
||||
#include "paddle/math/Matrix.h"
|
||||
#include "paddle/math/Vector.h"
|
||||
#include "paddle/parameter/Argument.h"
|
||||
#pragma once
|
||||
|
||||
namespace paddle {
|
||||
namespace capi {
|
||||
|
||||
enum CType { kIVECTOR = 0, kMATRIX, kARGUMENTS, kGRADIENT_MACHINE };
|
||||
|
||||
#define STRUCT_HEADER CType type;
|
||||
|
||||
struct CHeader {
|
||||
STRUCT_HEADER
|
||||
};
|
||||
|
||||
struct CIVector {
|
||||
STRUCT_HEADER
|
||||
IVectorPtr vec;
|
||||
|
||||
CIVector() : type(kIVECTOR) {}
|
||||
};
|
||||
|
||||
struct CMatrix {
|
||||
STRUCT_HEADER
|
||||
MatrixPtr mat;
|
||||
|
||||
CMatrix() : type(kMATRIX) {}
|
||||
};
|
||||
|
||||
struct CArguments {
|
||||
STRUCT_HEADER
|
||||
std::vector<paddle::Argument> args;
|
||||
|
||||
CArguments() : type(kARGUMENTS) {}
|
||||
|
||||
template <typename T>
|
||||
paddle_error accessSeqPos(uint64_t ID, uint32_t nestedLevel, T callback) {
|
||||
if (ID >= args.size()) return kPD_OUT_OF_RANGE;
|
||||
switch (nestedLevel) {
|
||||
case 0:
|
||||
callback(args[ID].sequenceStartPositions);
|
||||
break;
|
||||
case 1:
|
||||
callback(args[ID].subSequenceStartPositions);
|
||||
break;
|
||||
default:
|
||||
return kPD_OUT_OF_RANGE;
|
||||
}
|
||||
return kPD_NO_ERROR;
|
||||
}
|
||||
};
|
||||
|
||||
struct CGradientMachine {
|
||||
STRUCT_HEADER
|
||||
paddle::GradientMachinePtr machine;
|
||||
|
||||
CGradientMachine() : type(kGRADIENT_MACHINE) {}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline T* cast(void* ptr) {
|
||||
return reinterpret_cast<T*>(ptr);
|
||||
}
|
||||
} // namespace capi
|
||||
} // namespace paddle
|
@ -0,0 +1,10 @@
|
||||
#ifndef __PADDLE_PADDLE_CAPI_CONFIG_H_INCLUDED__
|
||||
#define __PADDLE_PADDLE_CAPI_CONFIG_H_INCLUDED__
|
||||
|
||||
typedef @PADDLE_FLOAT_TYPE@ paddle_real;
|
||||
|
||||
// Since we only support linux and macos in compile, always use clang or
|
||||
// gcc 4.8+. DLL_IMPORT/DLL_EXPORT is as simple as below.
|
||||
#define PD_API __attribute__((visibility("default")))
|
||||
|
||||
#endif
|
@ -0,0 +1,30 @@
|
||||
/* 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. */
|
||||
|
||||
#ifndef __PADDLE_CAPI_ERROR_H__
|
||||
#define __PADDLE_CAPI_ERROR_H__
|
||||
|
||||
/**
|
||||
* Error Type for Paddle API.
|
||||
*/
|
||||
typedef enum {
|
||||
kPD_NO_ERROR = 0,
|
||||
kPD_NULLPTR = 1,
|
||||
kPD_OUT_OF_RANGE = 2,
|
||||
kPD_PROTOBUF_ERROR = 3,
|
||||
kPD_NOT_SUPPORTED = 4,
|
||||
kPD_UNDEFINED_ERROR = -1,
|
||||
} paddle_error;
|
||||
|
||||
#endif
|
@ -0,0 +1,2 @@
|
||||
*.bin
|
||||
build-*
|
@ -0,0 +1,3 @@
|
||||
# C-API Example Usage
|
||||
|
||||
* [Model Inference](./model_inference/README.md)
|
@ -0,0 +1,42 @@
|
||||
# Use C-API for Model Inference
|
||||
|
||||
There are several examples in this directory about how to use Paddle C-API for model inference.
|
||||
|
||||
## Convert configuration file to protobuf binary.
|
||||
|
||||
Firstly, the user should convert Paddle's model configuration file into a protobuf binary file. In each example directory, there is a file named `convert_protobin.sh`. It will convert `trainer_config.conf` into `trainer_config.bin`.
|
||||
|
||||
The `convert_protobin.sh` is very simple, just invoke `dump_config` Python module to dump the binary file. The command line usages are:
|
||||
|
||||
```bash
|
||||
python -m paddle.utils.dump_config YOUR_CONFIG_FILE 'CONFIG_EXTRA_ARGS' --binary > YOUR_CONFIG_FILE.bin
|
||||
```
|
||||
|
||||
## Initialize paddle
|
||||
|
||||
```c++
|
||||
char* argv[] = {"--use_gpu=False"};
|
||||
paddle_init(1, (char**)argv);
|
||||
```
|
||||
|
||||
We must initialize global context before we invoke other interfaces in Paddle. The initialize commands just like the `paddle_trainer` command line arguments. `paddle train --help`, will show the list of arguments. The most important argument is `use_gpu` or not.
|
||||
|
||||
## Load network and parameters
|
||||
|
||||
```c
|
||||
paddle_gradient_machine machine;
|
||||
paddle_gradient_machine_create_for_inference(&machine, config_file_content, content_size));
|
||||
paddle_gradient_machine_load_parameter_from_disk(machine, "./some_where_to_params"));
|
||||
```
|
||||
|
||||
The gradient machine is a Paddle concept, which represents a neural network can be forwarded and backward. We can create a gradient machine fo model inference, and load the parameter files from disk.
|
||||
|
||||
Moreover, if we want to inference in multi-thread, we could create a thread local gradient machine which shared the same parameter by using `paddle_gradient_machine_create_shared_param` API. Please reference `multi_thread` as an example.
|
||||
|
||||
## Create input
|
||||
|
||||
The input of a neural network is an `arguments`. The examples in this directory will show how to construct different types of inputs for prediction. Please look at `dense`, `sparse_binary`, `sequence` for details.
|
||||
|
||||
## Get inference
|
||||
|
||||
After invoking `paddle_gradient_machine_forward`, we could get the output of the neural network. The `value` matrix of output arguments will store the neural network output values. If the output is a `SoftmaxActivation`, the `value` matrix are the probabilities of each input samples. The height of output matrix is number of sample. The width is the number of categories.
|
@ -0,0 +1,26 @@
|
||||
#ifndef __CAPI_EXAMPLE_COMMON_H__
|
||||
#define __CAPI_EXAMPLE_COMMON_H__
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CHECK(stmt) \
|
||||
do { \
|
||||
paddle_error __err__ = stmt; \
|
||||
if (__err__ != kPD_NO_ERROR) { \
|
||||
fprintf(stderr, "Invoke paddle error %d \n" #stmt, __err__); \
|
||||
exit(__err__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void* read_config(const char* filename, long* size) {
|
||||
FILE* file = fopen(filename, "r");
|
||||
if (file == NULL) return NULL;
|
||||
fseek(file, 0L, SEEK_END);
|
||||
*size = ftell(file);
|
||||
fseek(file, 0L, SEEK_SET);
|
||||
void* buf = malloc(*size);
|
||||
fread(buf, 1, *size, file);
|
||||
fclose(file);
|
||||
return buf;
|
||||
}
|
||||
#endif
|
@ -0,0 +1,6 @@
|
||||
project(dense)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
aux_source_directory(. SRC_LIST)
|
||||
add_executable(${PROJECT_NAME} ${SRC_LIST})
|
||||
set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 99)
|
||||
target_link_libraries(${PROJECT_NAME} -lpaddle_capi_shared)
|
@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
python -m paddle.utils.dump_config trainer_config.py '' --binary > trainer_config.bin
|
@ -0,0 +1,69 @@
|
||||
#include <paddle/capi.h>
|
||||
#include <time.h>
|
||||
#include "../common/common.h"
|
||||
|
||||
#define CONFIG_BIN "./trainer_config.bin"
|
||||
|
||||
int main() {
|
||||
// Initalize Paddle
|
||||
char* argv[] = {"--use_gpu=False"};
|
||||
CHECK(paddle_init(1, (char**)argv));
|
||||
|
||||
// Reading config binary file. It is generated by `convert_protobin.sh`
|
||||
long size;
|
||||
void* buf = read_config(CONFIG_BIN, &size);
|
||||
|
||||
// Create a gradient machine for inference.
|
||||
paddle_gradient_machine machine;
|
||||
CHECK(paddle_gradient_machine_create_for_inference(&machine, buf, (int)size));
|
||||
CHECK(paddle_gradient_machine_randomize_param(machine));
|
||||
|
||||
// Loading parameter. Uncomment the following line and change the directory.
|
||||
// CHECK(paddle_gradient_machine_load_parameter_from_disk(machine,
|
||||
// "./some_where_to_params"));
|
||||
paddle_arguments in_args = paddle_arguments_create_none();
|
||||
|
||||
// There is only one input of this network.
|
||||
CHECK(paddle_arguments_resize(in_args, 1));
|
||||
|
||||
// Create input matrix.
|
||||
paddle_matrix mat = paddle_matrix_create(/* sample_num */ 1,
|
||||
/* size */ 784,
|
||||
/* useGPU */ false);
|
||||
srand(time(0));
|
||||
paddle_real* array;
|
||||
|
||||
// Get First row.
|
||||
CHECK(paddle_matrix_get_row(mat, 0, &array));
|
||||
|
||||
for (int i = 0; i < 784; ++i) {
|
||||
array[i] = rand() / ((float)RAND_MAX);
|
||||
}
|
||||
|
||||
CHECK(paddle_arguments_set_value(in_args, 0, mat));
|
||||
|
||||
paddle_arguments out_args = paddle_arguments_create_none();
|
||||
CHECK(paddle_gradient_machine_forward(machine,
|
||||
in_args,
|
||||
out_args,
|
||||
/* isTrain */ false));
|
||||
paddle_matrix prob = paddle_matrix_create_none();
|
||||
|
||||
CHECK(paddle_arguments_get_value(out_args, 0, prob));
|
||||
|
||||
CHECK(paddle_matrix_get_row(prob, 0, &array));
|
||||
|
||||
printf("Prob: ");
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
printf("%.2f ", array[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
CHECK(paddle_matrix_destroy(prob));
|
||||
CHECK(paddle_arguments_destroy(out_args));
|
||||
CHECK(paddle_matrix_destroy(mat));
|
||||
CHECK(paddle_arguments_destroy(in_args));
|
||||
CHECK(paddle_gradient_machine_destroy(machine));
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
from paddle.trainer_config_helpers import *
|
||||
|
||||
img = data_layer(name='pixel', size=784)
|
||||
|
||||
hidden = fc_layer(
|
||||
input=img,
|
||||
size=200,
|
||||
param_attr=ParamAttr(name='hidden.w'),
|
||||
bias_attr=ParamAttr(name='hidden.b'))
|
||||
|
||||
prob = fc_layer(
|
||||
input=hidden,
|
||||
size=10,
|
||||
act=SoftmaxActivation(),
|
||||
param_attr=ParamAttr(name='prob.w'),
|
||||
bias_attr=ParamAttr(name='prob.b'))
|
||||
|
||||
outputs(prob)
|
@ -0,0 +1,73 @@
|
||||
# This file is used to ignore files which are generated
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
*~
|
||||
*.autosave
|
||||
*.a
|
||||
*.core
|
||||
*.moc
|
||||
*.o
|
||||
*.obj
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.so.*
|
||||
*_pch.h.cpp
|
||||
*_resource.rc
|
||||
*.qm
|
||||
.#*
|
||||
*.*#
|
||||
core
|
||||
!core/
|
||||
tags
|
||||
.DS_Store
|
||||
.directory
|
||||
*.debug
|
||||
Makefile*
|
||||
*.prl
|
||||
*.app
|
||||
moc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
Thumbs.db
|
||||
*.res
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
|
||||
# xemacs temporary files
|
||||
*.flc
|
||||
|
||||
# Vim temporary files
|
||||
.*.swp
|
||||
|
||||
# Visual Studio generated files
|
||||
*.ib_pdb_index
|
||||
*.idb
|
||||
*.ilk
|
||||
*.pdb
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*vcproj.*.*.user
|
||||
*.ncb
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.vcxproj
|
||||
*vcxproj.*
|
||||
|
||||
# MinGW generated files
|
||||
*.Debug
|
||||
*.Release
|
||||
|
||||
# Python byte code
|
||||
*.pyc
|
||||
|
||||
# Binaries
|
||||
# --------
|
||||
*.dll
|
||||
*.exe
|
||||
|
@ -0,0 +1,8 @@
|
||||
project(multi_thread)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
aux_source_directory(. SRC_LIST)
|
||||
add_executable(${PROJECT_NAME} ${SRC_LIST})
|
||||
find_package (Threads)
|
||||
set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 99)
|
||||
target_link_libraries(${PROJECT_NAME} -lpaddle_capi_shared
|
||||
${CMAKE_THREAD_LIBS_INIT})
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue