Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wrap Tensorflow by Cython and enable C++ to call it?

Sometimes I'd like to build the Tensorflow application as a dynamic linked library so that it can be called by other C++ applications. Although I can use Tensorflow C++ API to build the data flow graph, I'd prefer to use it's Python API because many shared models are written by that.

Following is one of my approaches that use Cython to wrap the Tensorflow application. However, it ended up with "tensorflow.pxd not found" error.

Detail

At first, here is the python code:

#File Name: HelloTensorflow.pyx

cimport numpy as np
cimport tensorflow as tf

cdef public float ExecuteTensorFlow():
        x = tf.placeholder(tf.float32, [1, 2])
        w = tf.constant([0.2, 0.3], tf.float32)
        b = tf.constant( -0.1, tf.float32)
        linearModel = tf.matmul(x, tf.reshape(w, shape=[2, 1])) + b

        session = tf.Session()
        result = session.run(linearModel, feed_dict={x: np.reshape([-0.1, -0.4], [1, 2])} )

        return np.reshape(result, [])

and the C++ source code that will call it:

// File Name: CppCallPython.cpp

#include <Python.h>
#include "HelloTensorflow.h"
#include <iostream>

void Run(void)
{
        Py_Initialize();
        initHelloTensorflow();
                std::cout<<"\t Execute Tensorflow:\n";
                float result = ExecuteTensorFlow();
                std::cout<<"\t Result = "
                         <<result<<std::endl;
        Py_Finalize();
}

int main(void)
{
        ::Run();
}

and build the python code to the dynamic library by:

# File Name: createPythonLib.py

from distutils.core import setup
from Cython.Build import cythonize

setup( ext_modules = cythonize("HelloTensorflow.pyx") )

Finally, use Makefile to execute the build:

# File Name: Makefile
Target = CppCallPython

# Compiler
CC = LC_MESSAGES=C g++
CXXFLAGS = -Wall -Wextra -g

LIB_PYTHON2 = $(shell python2-config --cflags --ldflags)
MODULE_NAME = HelloTensorflow
LIB_MODULE = -L./ $(MODULE_NAME).so


.PHONY: all
all: pythonLib  cppExecutable
        echo Build Finished.

pythonLib:
        python createPythonLib.py  build_ext --inplace

cppExecutable: $(MODULE_NAME).h
        $(CC) $(CXXFLAGS) $(Target).cpp $(LIB_MODULE)  $(LIB_PYTHON2)  -o $(Target)

As mentioned above, it ended up with "tensorflow.pxd not found" error:

missing cimport in module 'tensorflow': HelloTensorflow.pyx
Compiling HelloTensorflow.pyx because it changed.
[1/1] Cythonizing HelloTensorflow.pyx

Error compiling Cython file:
------------------------------------------------------------
...
cimport numpy as np
cimport tensorflow as tf
       ^
------------------------------------------------------------

HelloTensorflow.pyx:2:8: 'tensorflow.pxd' not found
Traceback (most recent call last):
  File "createPythonLib.py", line 4, in <module>
    setup( ext_modules = cythonize("HelloTensorflow.pyx") )
  File "/usr/lib/python2.7/dist-packages/Cython/Build/Dependencies.py", line 877, in cythonize
    cythonize_one(*args)
  File "/usr/lib/python2.7/dist-packages/Cython/Build/Dependencies.py", line 997, in cythonize_one
    raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: HelloTensorflow.pyx
makefile:18: recipe for target 'pythonLib' failed
make: *** [pythonLib] Error 1

Does this mean that I can't wrap Tensorflow application with Cython, because the "*.pxd" is not provided by Tensorflow? Is there any other way?

System

Ubuntu 16.04 LTS
Tensorflow 1.2.0 GPU
gcc version 5.4.0
Python: Python 2.7.12
Cython version 0.23.4

like image 642
WhiteRivers Avatar asked Jun 22 '17 11:06

WhiteRivers


1 Answers

cimport is a Cython-specific mechanism for importing statically defined type information from a pxd file. It does not look like tensorflow provides such a file (hence the error message). It looks like you're just using tensorflow as a Python module, in which case you should import it instead (this probably also applies to numpy too: it does define a .pxd file, but to access the normal numpy functions you should also import it).

Give that all your code is basically untyped Python code you should not expect huge speed improvements from using Cython.

like image 156
DavidW Avatar answered Oct 15 '22 09:10

DavidW