Skip to content

mxnet如何从python调用cpp?

Hu Shiwen edited this page Jul 21, 2017 · 7 revisions

发现不少人关心这个问题.简单的说一下这个基本过程吧.

通过ctypes调用mxnet.dll中导出的c函数

在base.py中调用ctypes.CDLL加载mxnet.dll.然后装入全局变量_Lib中.

symbol.py初始化

首先检查MXNET_ENABLE_CYTHON环境变量检测CYTHON是否启用. 如启用,根据python版本导入对应的CYTHON版本的SymbolBase类,_set_symbol_class,和_symbol_creator函数 如果没有则导入ctypes版本的SymbolBase类,_set_symbol_class,和_symbol_creator函数

随后以python类SymbolBase(上面导入的)为基类定义python类Symbol,该类是对应c++中的Symbol的包装.这里不展开说了.

最后调用_init_symbol_module开始关键的初始化过程.在symbol这个python module中注入用来创建op的代理函数.就是比如mx.symbol.FullyConnected这样的函数

_init_symbol_module

以下全部C函数的调用通过ctypes实现,用的是全局变量_Lib

1.用python类Symbol为参数调用_set_symbol_class,该函数将python类Symbol保存在_symbol_cls备用

2.调用C函数MXListAllOpNames.获取全部op的名字

3.遍历每一个op名字.调用C函数NNGetOpHandle得到op的Handle

4.通过Handle调用C函数MXSymbolGetAtomicSymbolInfo获取op的详细信息

5.根据op详细信息动态构造python函数.该函数就是创建op用的代理函数(代理函数的功能在下一节)

6.将5中构造的函数动态注入mxnet.symbol模块(部分op注入到其他模块)

最后当你调用比如mx.symbol.FullyConnected时.就会调用FullyConnected对应的在5中创建的函数.

代理函数

以下全部C函数的调用通过ctypes实现,同样用的是全局变量_Lib

1.调用C函数MXSymbolCreateAtomicSymbol来创建Symbol实例

2.然后用返回的SymbolHandle调用_symbol_cls(前面保存的)创建python类Symbol的实例.这样一个python类Symbol的实例就和一个c++中的Symbol实例对应起来了

3.接受参数,比如 mx.symbol.FullyConnected(data=data, weight=w, name="fc1", num_hidden=128) 用这些参数调用Symbol._compose

4._compose用传入的参数调用C函数MXSymbolCompose,MXSymbolCompose会根据这些参数,完成Symbol组装.