Python与OpenMP C扩展
我有一个C语言扩展,想要使用OpenMP。不过,当我导入我的模块时,出现了导入错误:
ImportError: /home/.../_entropysplit.so: undefined symbol: GOMP_parallel_end
我在编译这个模块时用了-fopenmp和-lgomp选项。这个错误是因为我的Python安装没有用-fopenmp选项编译吗?我需要从源代码重新编译Python吗?还是说还有其他可能性?在我的模块中,实际上只有这一次使用了openmp:
unsigned int feature_index;
#pragma omp parallel for
for (feature_index = 0; feature_index < num_features; feature_index++) {
如果可以的话,我希望继续使用openmp,因为它非常简单,而且在这种情况下,使用并行处理非常合适。
编辑:我下定决心,重新编译了支持OpenMP的Python。现在我的模块运行得很好,但这并不是一个好的解决方案。如果需要完全重新编译Python,我就没法分发这个模块了。那么有没有人知道有什么解决办法?ctypes可以用吗?
解决了!这其实是一个简单的链接问题。(我为了这个还重建了Python?)在编译模块时,OpenMP没有被正确链接。所以,确实可以加载一个使用OpenMP的C语言Python扩展。
3 个回答
这其实是个简单的链接问题。在编译这个模块的时候,OpenMP没有被正确链接。所以,确实可以加载一个使用了OpenMP的C语言Python扩展。你需要在编译时加上-fopenmp这个选项,链接时加上-lgomp这个选项。如果你在用distutils,确保你的setup.py配置正确。重新编译Python也有效,我猜是因为我已经把OpenMP和Python正确链接了,所以当Python加载这个模块时,库已经链接好了。
我知道这个帖子有点旧,但我想分享一下我的经历,因为我也遇到了同样的问题,只不过我是通过命令行使用f2py。我最开始是用下面的命令来编译我的OpenMP支持的Fortran 90子程序:
f2py --fcompiler=gfortran --f90flags='-fopenmp -lgomp' -m sub -c sub.90
这个命令成功创建了一个共享对象文件sub.so。但是,当我试图在Python环境中导入这个文件时,出现了类似未定义符号的导入错误。正如原作者所说,这个问题是因为我同时给编译器传递了-fopenmp和-lgomp这两个参数,而实际上只需要把-fopenmp传给编译器,把-lgomp传给链接器。
所以,我应该这样做:
f2py --fcompiler=gfortran --f90flags='-fopenmp' -lgomp -m sub -c sub.f90
就这样,问题解决了,我现在可以顺利导入我的子程序了。
为了让你更清楚,这里是你应该如何写setup.py文件的样子:
ext = Extension(
'milk.unsupervised._som',
sources = ['milk/unsupervised/_som.cpp'],
extra_compile_args=['-fopenmp'],
extra_link_args=['-lgomp'])
...
setup(..., ext_modules = [ext])