Skip to content

Commit

Permalink
Expose paddle.framework by pybind11 (PaddlePaddle#2793)
Browse files Browse the repository at this point in the history
* Expose paddle.framework by pybind11

* Export paddle.framework.{Scope, Variable} to paddle.v2.framework.core.
* See python/paddle/v2/framework/tests/test_scope.py for Python usage
* See paddle/pybind/pybind.cc for C++ bind code.

* add copyright
  • Loading branch information
reyoung authored and jacquesqiao committed Jul 11, 2017
1 parent ef67d08 commit 27b196b
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ third_party/

# clion workspace.
cmake-build-*

# generated while compiling
python/paddle/v2/framework/core.so
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ include(external/swig) # download, build, install swig
include(external/warpctc) # download, build, install warpctc
include(external/any) # download libn::any
include(external/eigen) # download eigen3
include(external/pybind11) # download pybind11

include(cudnn) # set cudnn libraries, must before configure
include(configure) # add paddle env configuration
Expand Down
30 changes: 30 additions & 0 deletions cmake/external/pybind11.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
INCLUDE(ExternalProject)

SET(PYBIND_SOURCE_DIR ${THIRD_PARTY_PATH}/pybind)

INCLUDE_DIRECTORIES(${PYBIND_SOURCE_DIR}/src/extern_pybind/include)

ExternalProject_Add(
extern_pybind
${EXTERNAL_PROJECT_LOG_ARGS}
GIT_REPOSITORY "https://github.com/pybind/pybind11.git"
GIT_TAG "v2.1.1"
PREFIX ${PYBIND_SOURCE_DIR}
UPDATE_COMMAND ""
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)

if (${CMAKE_VERSION} VERSION_LESS "3.3.0")
set(dummyfile ${CMAKE_CURRENT_BINARY_DIR}/pybind_dummy.c)
file(WRITE ${dummyfile} "const char * dummy_any = \"${dummyfile}\";")
add_library(pybind STATIC ${dummyfile})
else()
add_library(pybind INTERFACE)
endif()

add_dependencies(pybind extern_pybind)

LIST(APPEND external_project_dependencies pybind)
3 changes: 3 additions & 0 deletions cmake/external/python.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ INCLUDE(python_module)
FIND_PACKAGE(PythonInterp 2.7)
IF(WITH_PYTHON)
FIND_PACKAGE(PythonLibs 2.7)
# Fixme: Maybe find a static library. Get SHARED/STATIC by FIND_PACKAGE.
ADD_LIBRARY(python SHARED IMPORTED GLOBAL)
SET_PROPERTY(TARGET python PROPERTY IMPORTED_LOCATION ${PYTHON_LIBRARIES})
ENDIF(WITH_PYTHON)

SET(py_env "")
Expand Down
4 changes: 3 additions & 1 deletion cmake/flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ set(COMMON_FLAGS
-Wno-unused-function
-Wno-error=literal-suffix
-Wno-error=sign-compare
-Wno-error=unused-local-typedefs)
-Wno-error=unused-local-typedefs
-Wno-error=parentheses-equality # Warnings in Pybind11
)

set(GPU_COMMON_FLAGS
-fPIC
Expand Down
1 change: 1 addition & 0 deletions paddle/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ if(Boost_FOUND)
add_subdirectory(memory)
add_subdirectory(platform)
add_subdirectory(framework)
add_subdirectory(pybind)
endif()

if(WITH_C_API)
Expand Down
1 change: 1 addition & 0 deletions paddle/pybind/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cc_library(paddle_pybind SHARED SRCS pybind.cc DEPS pybind python)
46 changes: 46 additions & 0 deletions paddle/pybind/pybind.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* 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 <paddle/framework/scope.h>
#include <pybind11/pybind11.h>

namespace py = pybind11;
namespace pd = paddle::framework;

PYBIND11_PLUGIN(core) {
py::module m("core", "C++ core of Paddle Paddle");

py::class_<pd::Variable>(m, "Variable", R"DOC(Variable Class.
All parameter, weight, gradient are variables in Paddle.
)DOC")
.def("is_int", [](const pd::Variable& var) { return var.IsType<int>(); })
.def("set_int",
[](pd::Variable& var, int val) -> void {
*var.GetMutable<int>() = val;
})
.def("get_int",
[](const pd::Variable& var) -> int { return var.Get<int>(); });

py::class_<pd::Scope, std::shared_ptr<pd::Scope>>(m, "Scope")
.def(py::init<const std::shared_ptr<pd::Scope>&>())
.def("get_var",
&pd::Scope::GetVariable,
py::return_value_policy::reference)
.def("create_var",
&pd::Scope::CreateVariable,
py::return_value_policy::reference);

return m.ptr();
}
9 changes: 8 additions & 1 deletion python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,17 @@ endif(WITH_GOLANG)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in
${CMAKE_CURRENT_BINARY_DIR}/setup.py)


add_custom_command(OUTPUT ${PROJ_ROOT}/python/paddle/v2/framework/core.so
COMMAND cmake -E copy $<TARGET_FILE:paddle_pybind> ${PROJ_ROOT}/python/paddle/v2/framework/core.so
DEPENDS paddle_pybind)
add_custom_target(copy_paddle_pybind ALL DEPENDS ${PROJ_ROOT}/python/paddle/v2/framework/core.so)


add_custom_command(OUTPUT ${OUTPUT_DIR}/.timestamp
COMMAND env ${py_env} ${PYTHON_EXECUTABLE} setup.py bdist_wheel
COMMAND ${CMAKE_COMMAND} -E touch ${OUTPUT_DIR}/.timestamp
DEPENDS gen_proto_py framework_py_proto ${PY_FILES} ${external_project_dependencies} ${COPY_PADDLE_MASTER})
DEPENDS gen_proto_py copy_paddle_pybind framework_py_proto ${PY_FILES} ${external_project_dependencies} ${COPY_PADDLE_MASTER})

add_custom_target(paddle_python ALL DEPENDS
${OUTPUT_DIR}/.timestamp)
Expand Down
2 changes: 1 addition & 1 deletion python/paddle/v2/framework/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
add_python_test(test_framework test_protobuf.py)
add_python_test(test_framework test_protobuf.py test_scope.py)
4 changes: 4 additions & 0 deletions python/paddle/v2/framework/tests/test_protobuf.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@ def test_all(self):
attr.type = attr_type_lib.FLOAT
op_proto.type = "cos"
self.assertTrue(op_proto.IsInitialized())


if __name__ == "__main__":
unittest.main()
37 changes: 37 additions & 0 deletions python/paddle/v2/framework/tests/test_scope.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import paddle.v2.framework.core
import unittest


class TestScope(unittest.TestCase):
def test_create_destroy(self):
paddle_c = paddle.v2.framework.core
scope = paddle_c.Scope(None)
self.assertIsNotNone(scope)
scope_with_parent = paddle_c.Scope(scope)
self.assertIsNotNone(scope_with_parent)

def test_none_variable(self):
paddle_c = paddle.v2.framework.core
scope = paddle_c.Scope(None)
self.assertIsNone(scope.get_var("test"))

def test_create_var_get_var(self):
paddle_c = paddle.v2.framework.core
scope = paddle_c.Scope(None)
var_a = scope.create_var("var_a")
self.assertIsNotNone(var_a)
self.assertIsNotNone(scope.get_var('var_a'))
scope2 = paddle_c.Scope(scope)
self.assertIsNotNone(scope2.get_var('var_a'))

def test_var_get_int(self):
paddle_c = paddle.v2.framework.core
scope = paddle_c.Scope(None)
var = scope.create_var("test_int")
var.set_int(10)
self.assertTrue(var.is_int())
self.assertEqual(10, var.get_int())


if __name__ == '__main__':
unittest.main()
4 changes: 3 additions & 1 deletion python/setup.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ setup(name='paddle',
description='Parallel Distributed Deep Learning',
install_requires=setup_requires,
packages=packages,
package_data={'paddle.v2.master': ['libpaddle_master.so'], },
package_data={'paddle.v2.master': ['libpaddle_master.so'],
'paddle.v2.framework': ['core.so']
},
package_dir={
'': '${CMAKE_CURRENT_SOURCE_DIR}',
# The paddle.v2.framework.proto will be generated while compiling.
Expand Down

0 comments on commit 27b196b

Please sign in to comment.