提交 fbb1b0e4 编写于 作者: Y Yu Yang

Start Doing C-API for predict.

上级 495649af
......@@ -8,7 +8,7 @@ add_subdirectory(gserver)
add_subdirectory(pserver)
add_subdirectory(trainer)
add_subdirectory(scripts)
add_subdirectory(capi)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in
${CMAKE_CURRENT_SOURCE_DIR}/setup.py)
......
#include "PaddleCAPI.h"
#include "PaddleCAPIPrivate.h"
#define cast(v) paddle::capi::cast<paddle::capi::CArguments>(v)
extern "C" {
int PDArgsCreateNone(PD_Arguments* args) {
auto ptr = new paddle::capi::CArguments();
*args = ptr;
return PD_NO_ERROR;
}
int PDArgsDestroy(PD_Arguments args) {
if (args == nullptr) return PD_NULLPTR;
delete cast(args);
return PD_NO_ERROR;
}
int PDArgsGetSize(PD_Arguments args, uint64_t* size) {
if (args == nullptr || size == nullptr) return PD_NULLPTR;
*size = cast(args)->args.size();
return PD_NO_ERROR;
}
int PDArgsResize(PD_Arguments args, uint64_t size) {
if (args == nullptr) return PD_NULLPTR;
cast(args)->args.resize(size);
return PD_NO_ERROR;
}
int PDArgsSetValue(PD_Arguments args, uint64_t ID, PD_Matrix mat) {
if (args == nullptr || mat == nullptr) return PD_NULLPTR;
auto m = paddle::capi::cast<paddle::capi::CMatrix>(mat);
if (m->mat == nullptr) return PD_NULLPTR;
auto a = cast(args);
if (ID >= a->args.size()) return PD_OUT_OF_RANGE;
a->args[ID].value = m->mat;
return PD_NO_ERROR;
}
int PDArgsGetValue(PD_Arguments args, uint64_t ID, PD_Matrix mat) {
if (args == nullptr || mat == nullptr) return PD_NULLPTR;
auto m = paddle::capi::cast<paddle::capi::CMatrix>(mat);
auto a = cast(args);
if (ID >= a->args.size()) return PD_OUT_OF_RANGE;
m->mat = a->args[ID].value;
return PD_NO_ERROR;
}
}
if (WITH_DOUBLE)
set(PADDLE_FLOAT_TYPE double)
else ()
set(PADDLE_FLOAT_TYPE float)
endif()
configure_file(config.h.in config.h @ONLY)
set(CAPI_HEADER
PaddleCAPI.h)
set(CAPI_PRIVATE_HEADER
PaddleCAPIPrivate.h)
file(GLOB CAPI_SOURCES *.cpp)
add_library(paddle_capi SHARED ${CAPI_SOURCES})
target_include_directories(paddle_capi PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
add_dependencies(paddle_capi gen_proto_cpp)
target_link_libraries(paddle_capi
paddle_gserver
paddle_function
paddle_pserver
paddle_trainer_lib
paddle_network
paddle_math
paddle_utils
paddle_parameter
paddle_proto
paddle_cuda
${PROTOBUF_LIBRARY}
${LIBGLOG_LIBRARY}
${GFLAGS_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${CBLAS_LIBS}
${ZLIB_LIBRARIES}
${INTERAL_LIBS}
${CMAKE_DL_LIBS})
set(PADDLE_CAPI_INC_PATH
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})
if (WITH_TESTING)
add_subdirectory(tests)
endif()
#include "PaddleCAPI.h"
#include "PaddleCAPIPrivate.h"
#include "hl_cuda.h"
#define cast(v) paddle::capi::cast<paddle::capi::CMatrix>(v)
extern "C" {
int PDMatCreate(PD_Matrix* mat, uint64_t height, uint64_t width, bool useGpu) {
auto ptr = new paddle::capi::CMatrix();
ptr->mat = paddle::Matrix::create(height, width, false, useGpu);
*mat = ptr;
return PD_NO_ERROR;
}
int PDMatCreateNone(PD_Matrix* mat) {
auto ptr = new paddle::capi::CMatrix();
*mat = ptr;
return PD_NO_ERROR;
}
int PDMatDestroy(PD_Matrix mat) {
if (mat == nullptr) return PD_NULLPTR;
auto ptr = cast(mat);
delete ptr;
return PD_NO_ERROR;
}
int PDMatCopyToRow(PD_Matrix mat, uint64_t rowID, pd_real* rowArray) {
if (mat == nullptr) return PD_NULLPTR;
auto ptr = cast(mat);
if (ptr->mat == nullptr) return PD_NULLPTR;
if (rowID >= ptr->mat->getHeight()) return PD_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 PD_NO_ERROR;
}
int PDMatGetRow(PD_Matrix mat, uint64_t rowID, pd_real** rawRowBuffer) {
if (mat == nullptr) return PD_NULLPTR;
auto ptr = cast(mat);
if (ptr->mat == nullptr) return PD_NULLPTR;
if (rowID >= ptr->mat->getHeight()) return PD_OUT_OF_RANGE;
*rawRowBuffer = ptr->mat->getRowBuf(rowID);
return PD_NO_ERROR;
}
int PDMatGetShape(PD_Matrix mat, uint64_t* height, uint64_t* width) {
if (mat == nullptr) return PD_NULLPTR;
if (height != nullptr) {
*height = cast(mat)->mat->getHeight();
}
if (width != nullptr) {
*width = cast(mat)->mat->getWidth();
}
return PD_NO_ERROR;
}
}
#ifndef __PADDLE_PADDLE_CAPI_PADDLECAPI_H_INCLUDED__
#define __PADDLE_PADDLE_CAPI_PADDLECAPI_H_INCLUDED__
#include <stdbool.h>
#include <stdint.h>
#include "config.h"
#ifdef __cplusplus
extern "C" {
#endif
#define PD_NO_ERROR 0
#define PD_NULLPTR 1
#define PD_OUT_OF_RANGE 2
#define PD_UNDEFINED_ERROR -1
typedef void* PD_Vector;
int PDVecCreate(PD_Vector* vec, uint64_t size, bool useGpu);
int PDVecDestroy(PD_Vector vec);
int PDVecIsSparse(PD_Vector vec, bool* isSparse);
typedef void* PD_Matrix;
int PDMatCreate(PD_Matrix* mat, uint64_t height, uint64_t width, bool useGpu);
int PDMatDestroy(PD_Matrix mat);
int PDMatCopyToRow(PD_Matrix mat, uint64_t rowID, pd_real* rowArray);
int PDMatGetRow(PD_Matrix mat, uint64_t rowID, pd_real** rawRowBuffer);
int PDMatCreateNone(PD_Matrix* mat);
int PDMatGetShape(PD_Matrix mat, uint64_t* height, uint64_t* width);
typedef void* PD_Arguments;
int PDArgsCreateNone(PD_Arguments* args);
int PDArgsDestroy(PD_Arguments args);
int PDArgsGetSize(PD_Arguments args, uint64_t* size);
int PDArgsResize(PD_Arguments args, uint64_t size);
int PDArgsSetValue(PD_Arguments args, uint64_t ID, PD_Matrix mat);
int PDArgsGetValue(PD_Arguments args, uint64_t ID, PD_Matrix mat);
#ifdef __cplusplus
}
#endif
#endif
#include "PaddleCAPI.h"
#include "paddle/math/Matrix.h"
#include "paddle/math/Vector.h"
#include "paddle/parameter/Argument.h"
#pragma once
namespace paddle {
namespace capi {
struct CVector {
VectorPtr vec;
};
struct CMatrix {
MatrixPtr mat;
};
struct CArguments {
std::vector<paddle::Argument> args;
};
template <typename T>
inline T* cast(void* ptr) {
return reinterpret_cast<T*>(ptr);
}
}
}
#include "PaddleCAPI.h"
#include "PaddleCAPIPrivate.h"
#define cast(v) paddle::capi::cast<paddle::capi::CVector>(v)
extern "C" {
int PDVecCreate(PD_Vector* vec, uint64_t size, bool useGpu) {
auto ptr = new paddle::capi::CVector();
ptr->vec = paddle::Vector::create(size, useGpu);
*vec = ptr;
return PD_NO_ERROR;
}
int PDVecDestroy(PD_Vector vec) {
auto v = cast(vec);
v->vec.reset();
delete v;
return PD_NO_ERROR;
}
int PDVecIsSparse(PD_Vector vec, bool* isSparse) {
if (isSparse == nullptr || vec == nullptr) {
return PD_NULLPTR;
}
*isSparse = cast(vec)->vec->isSparse();
return PD_NO_ERROR;
}
}
#ifndef __PADDLE_PADDLE_CAPI_CONFIG_H_INCLUDED__
#define __PADDLE_PADDLE_CAPI_CONFIG_H_INCLUDED__
typedef @PADDLE_FLOAT_TYPE@ pd_real;
#endif
function(add_capi_unittest TARGET_NAME)
add_executable(
${TARGET_NAME}
${ARGN})
target_link_libraries(
${TARGET_NAME}
paddle_capi
paddle_test_main
${GTEST_LIBRARIES})
target_include_directories(${TARGET_NAME} PUBLIC ${PADDLE_CAPI_INC_PATH})
add_test(NAME ${TARGET_NAME} COMMAND ${TARGET_NAME})
endfunction()
add_capi_unittest(capi_test_mats test_Vector.cpp
test_Matrix.cpp test_Arguments.cpp)
#include "PaddleCAPI.h"
#include "gtest/gtest.h"
#include "paddle/utils/ThreadLocal.h"
static std::vector<pd_real> randomBuffer(size_t bufSize) {
auto& eng = paddle::ThreadLocalRandomEngine::get();
std::uniform_real_distribution<pd_real> dist(-1.0, 1.0);
std::vector<pd_real> retv;
retv.reserve(bufSize);
for (size_t i = 0; i < bufSize; ++i) {
retv.push_back(dist(eng));
}
return retv;
}
TEST(CAPIArguments, create) {
PD_Arguments args;
ASSERT_EQ(PD_NO_ERROR, PDArgsCreateNone(&args));
uint64_t size;
ASSERT_EQ(PD_NO_ERROR, PDArgsGetSize(args, &size));
ASSERT_EQ(0UL, size);
ASSERT_EQ(PD_NO_ERROR, PDArgsDestroy(args));
}
TEST(CAPIArguments, value) {
PD_Arguments args;
ASSERT_EQ(PD_NO_ERROR, PDArgsCreateNone(&args));
ASSERT_EQ(PD_NO_ERROR, PDArgsResize(args, 1));
PD_Matrix mat;
ASSERT_EQ(PD_NO_ERROR, PDMatCreate(&mat, 128, 64, false));
for (size_t i = 0; i < 128; ++i) {
std::vector<pd_real> sampleBuf = randomBuffer(64);
PDMatCopyToRow(mat, i, sampleBuf.data());
}
ASSERT_EQ(PD_NO_ERROR, PDArgsSetValue(args, 0, mat));
PD_Matrix val;
ASSERT_EQ(PD_NO_ERROR, PDMatCreateNone(&val));
ASSERT_EQ(PD_NO_ERROR, PDArgsGetValue(args, 0, val));
for (size_t i = 0; i < 128; ++i) {
pd_real* row1;
pd_real* row2;
ASSERT_EQ(PD_NO_ERROR, PDMatGetRow(mat, i, &row1));
ASSERT_EQ(PD_NO_ERROR, PDMatGetRow(val, i, &row2));
ASSERT_EQ(row1, row2);
}
ASSERT_EQ(PD_NO_ERROR, PDMatDestroy(val));
ASSERT_EQ(PD_NO_ERROR, PDMatDestroy(mat));
ASSERT_EQ(PD_NO_ERROR, PDArgsDestroy(args));
}
#include "PaddleCAPI.h"
#include "gtest/gtest.h"
TEST(CAPIMatrix, create) {
PD_Matrix mat;
ASSERT_EQ(PD_NO_ERROR, PDMatCreate(&mat, 128, 32, false));
std::vector<pd_real> sampleRow;
sampleRow.resize(32);
for (size_t i = 0; i < sampleRow.size(); ++i) {
sampleRow[i] = 1.0 / (i + 1.0);
}
ASSERT_EQ(PD_NO_ERROR, PDMatCopyToRow(mat, 0, sampleRow.data()));
ASSERT_EQ(PD_OUT_OF_RANGE, PDMatCopyToRow(mat, 128, sampleRow.data()));
pd_real* arrayPtr;
ASSERT_EQ(PD_NO_ERROR, PDMatGetRow(mat, 0, &arrayPtr));
for (size_t i = 0; i < sampleRow.size(); ++i) {
ASSERT_NEAR(sampleRow[i], arrayPtr[i], 1e-5);
}
uint64_t height, width;
ASSERT_EQ(PD_NO_ERROR, PDMatGetShape(mat, &height, &width));
ASSERT_EQ(128, height);
ASSERT_EQ(32, width);
ASSERT_EQ(PD_NO_ERROR, PDMatDestroy(mat));
}
TEST(CAPIMatrix, createNone) {
PD_Matrix mat;
ASSERT_EQ(PD_NO_ERROR, PDMatCreateNone(&mat));
ASSERT_EQ(PD_NO_ERROR, PDMatDestroy(mat));
}
#include "PaddleCAPI.h"
#include "gtest/gtest.h"
TEST(CAPIVector, create) {
PD_Vector tmp;
ASSERT_EQ(PD_NO_ERROR, PDVecCreate(&tmp, 128, false));
bool isSparse;
ASSERT_EQ(PD_NO_ERROR, PDVecIsSparse(tmp, &isSparse));
ASSERT_FALSE(isSparse);
ASSERT_EQ(PD_NO_ERROR, PDVecDestroy(tmp));
}
/* 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. */
#pragma once
/// Declare a force link file ID. It can be enabled by
/// `PADDLE_ENABLE_FORCE_LINK_FILE`. It is
///
/// Example:
///
/// In some_file.cpp
/// @code{cpp}
/// static paddle::InitFunction init([]{...});
/// PADDLE_REGISTER_FORCE_LINK_FILE(some_file)
/// @endcode{cpp}
///
/// In main.cpp
/// @code{cpp}
/// PADDLE_ENABLE_FORCE_LINK_FILE(some_file);
///
/// int main() {
/// ...
/// }
/// @endcode{cpp}
///
/// Then the InitFunction in some_file.cpp can be invoked.
#define PADDLE_REGISTER_FORCE_LINK_FILE(ID) \
int __paddle_register_force_link_file_##ID##_method__() { return 0; }
/// Enable a force link file. The file with ID's static variables could
/// be all initialized.
#define PADDLE_ENABLE_FORCE_LINK_FILE(ID) \
extern int __paddle_register_force_link_file_##ID##_method__(); \
static int __paddle_register_force_link_file_##ID##_handler__ = \
__paddle_register_force_link_file_##ID##_method__();
......@@ -15,3 +15,11 @@ if(NOT APPLE)
COMMAND ${PROJ_ROOT}/paddle/utils/tests/test_CustomStackTracePrint.sh
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endif()
add_library(test_class_registrar_lib STATIC
test_ClassRegistrarLib.cpp
test_ClassRegistrarGlobals.cpp)
add_simple_unittest(test_ClassRegistrar)
target_link_libraries(test_ClassRegistrar
test_class_registrar_lib)
/* 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 <gtest/gtest.h>
#include <paddle/utils/ForceLink.h>
#include "test_ClassRegistrarLib.h"
// Enable link test_ClassRegistrarLib.cpp
PADDLE_ENABLE_FORCE_LINK_FILE(test_registrar);
TEST(ClassRegistrar, test) {
std::vector<std::string> types;
gTestRegistrar_.forEachType(
[&types](const std::string& tp) { types.push_back(tp); });
ASSERT_EQ(1, types.size());
ASSERT_EQ("test", types[0]);
}
/* 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 "test_ClassRegistrarLib.h"
paddle::ClassRegistrar<BaseClass> gTestRegistrar_;
/* 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 "test_ClassRegistrarLib.h"
#include <paddle/utils/ForceLink.h>
BaseClass::~BaseClass() {}
class TestRegistrar : public BaseClass {
public:
TestRegistrar() {}
virtual ~TestRegistrar() {}
};
static paddle::InitFunction init([] {
gTestRegistrar_.registerClass(
"test", []() -> BaseClass* { return new TestRegistrar(); });
});
PADDLE_REGISTER_FORCE_LINK_FILE(test_registrar);
/* 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. */
#pragma once
#include "paddle/utils/ClassRegistrar.h"
class BaseClass {
public:
virtual ~BaseClass();
};
extern paddle::ClassRegistrar<BaseClass> gTestRegistrar_;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册