-
Notifications
You must be signed in to change notification settings - Fork 7
[Testing Team] Template testing tutorial using SWIG
Q & A:
Do I need to have figured out
nn4mc
's full installation before this? (Including nlohmann-json and h5cpp) Not necessarily
$ sudo apt-get install -y swig
$ sudo apt-get install python-dev #doesn't hurt to have
$ brew install swig
You can use your favorite method, but if you have to Google it just do this:
$ git fetch origin
Then set a local branch to track the remote testing branch.
$ git branch --track [testing_templates] origin/testing_templates
$ git checkout testing_templates
In this branch, all of the generated code from nn4mc will appear under the file called testing_output_files/
in root.
Now you are in the testing branch. Within this branch go to the testing_output_files/
folder. Whenever a new code is generated (I set out the generated codes to do to the `testing_output_files/code_test' folder in this branch).
Go to testing_output_files/src/activation/
If you are interested in testing activation.cpp
, it should already be good to go and just type `python3.7 -c "import activation" if there are no errors you should be able to start building testing code. However, if there are errors or you want to test code that is not wrapped yet, you might have to use the following instructions to wrap the code to be tested. If it needs compiling go to these instructions.
For this example I'm going to be testing activations.cpp
you can import the function prototypes that you want to read into Python this way:
activations.i:
/* File: activation.i:
This is the file that gives us enough to wrap the code.
Here we introduce headers that import the functions or header
files. Since activations.h also imports all of the function
prototypes from activation.cpp, you only need to import the
header.
*/
%include "../../code_test/activations.cpp"
%include "../../code_test/activations.h"
%module activation
%{
extern float activate(float input, int output_shape, char type);
extern float sigmoid(float input);
extern float softplus(float input);
extern float softsign(float input);
extern float hard_sigmoid(float input);
extern float exponential(float input);
extern float relu(float input);
extern float hyper_tan(float input);
extern float softmax(float input, int output_shape);
%}
extern float activate(float input, int output_shape, char type);
extern float sigmoid(float input);
extern float softplus(float input);
extern float softsign(float input);
extern float hard_sigmoid(float input);
extern float exponential(float input);
extern float relu(float input);
extern float hyper_tan(float input);
extern float softmax(float input, int output_shape);
Go to testing_output_files/src
and run:
$ swig -python -c++ activation.i
$ c++ -c -fpic ../../code_test/activations.cpp
$ c++ -c -fpic activation_wrap.cxx -I/usr/include/python3.5
$ c++ -shared activations.o activation_wrap.o -o _activation.so
If you compile this wrapper in python3.5, you should feel free to use it for python conda versions >=3.5.
For example, to test if it worked just type $ python3.7 -c "import activation"
into the command line and if there are no import errors you are ready to go.
$ swig -python -c++ activation.i
$ c++ -c -fpic ../../code_test/activations.cpp
$ c++ -c -fpic activation_wrap.cxx -I/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/include/python3.7m
$ c++ -bundle -flat_namespace activations.o activation_wrap.o -undefined suppress -o _activation.so
Then, when building your testing module, make sure you import the c code (now Python code) as:
testing_module.py:
import activation
from testing_output_files.template_test import TemplateTest
[...]
class ActivationTest(TemplateTest):
def __init__(self):
[...]
def individual_functions_test(self):
[...]
def passes(self)->bool:
[...] # this method is necessary to all TemplateTest objects
[Your Python code]
To access the functions specified in the activation
module, just type, for example, activation.sigmoid(3.5)
.
If you get an error that says that Python.h
wasn't found, that means that the include path in the second command is wrong or doesn't lead to the right folders. To find where python is installed in you Mac type:
$ find / -name 'Python.h'
for Linux machines: sudo apt-get install python-dev
Then substitute the path after the -I
part of the command for the path that you found using find
.
If you get an error saying ld: symbol(s) not found for architecture x86_64
, then substitute the last command for:
clang $(python3-config --ldflags) -dynamiclib activations_wrap.o activations.o -o _activations.so
In short, undefined symbol may occur when the function prototype in the .h
file is different than the implementation in the .cpp
.
In this case I'll be testing conv1d
, which requires activation.cpp
's functions. Here is the list of commands (for MacOS):
Go to the testing_output_files/
and run:
$ python -c "import numpy; print(numpy.get_include())"
See the path that gets printed from there and include that path in the following swig lines:
$ swig -python -c++ conv1d.i
$ c++ -c -fpic -I/Users/sarahaguasvivas/anaconda3/lib/python3.7/site-packages/numpy/core/include
../../code_test/conv1d.cpp ../../code_test/activations.cpp
$ c++ -c -fpic conv1d_wrap.cxx -I/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/include/python3.7m -I/Users/sarahaguasvivas/anaconda3/lib/python3.7/site-packages/numpy/core/include
$ c++ -bundle -flat_namespace conv1d.o activations.o conv1d_wrap.o -undefined suppress -o _conv1d.so