Python与OpenMP C扩展

29 投票
3 回答
7988 浏览
提问于 2025-04-16 03:19

我有一个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 个回答

3

这其实是个简单的链接问题。在编译这个模块的时候,OpenMP没有被正确链接。所以,确实可以加载一个使用了OpenMP的C语言Python扩展。你需要在编译时加上-fopenmp这个选项,链接时加上-lgomp这个选项。如果你在用distutils,确保你的setup.py配置正确。重新编译Python也有效,我猜是因为我已经把OpenMP和Python正确链接了,所以当Python加载这个模块时,库已经链接好了。

8

我知道这个帖子有点旧,但我想分享一下我的经历,因为我也遇到了同样的问题,只不过我是通过命令行使用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

就这样,问题解决了,我现在可以顺利导入我的子程序了。

20

为了让你更清楚,这里是你应该如何写setup.py文件的样子:

ext = Extension(
      'milk.unsupervised._som',
      sources = ['milk/unsupervised/_som.cpp'],
      extra_compile_args=['-fopenmp'],
      extra_link_args=['-lgomp'])


...
setup(..., ext_modules = [ext])

撰写回答