29

我有一个 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 扩展

4

3 回答 3

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])
于 2010-10-08T19:25:14.073 回答
8

我知道这是一篇过时的帖子,但我会分享我的经验,因为我也遇到了同样的问题,但是在命令行使用f2py时。我最初使用 OpenMP 编译启用了 Fortran 90 的子例程

f2py --fcompiler=gfortran --f90flags='-fopenmp -lgomp' -m sub -c sub.90

成功创建了共享对象sub.so。但是,尝试从 Python shell 导入它会产生类似的未定义符号ImportError。但是,正如原作者所说,这是因为我试图将 -fopenmp 和 -lgomp 都传递给编译器,而只有 -fopenmp 应该传递给它,而 -lgomp 应该传递给链接器。

因此,我应该一直在做以下事情

f2py --fcompiler=gfortran --f90flags='-fopenmp' -lgomp -m sub -c sub.f90

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

于 2013-12-06T02:33:24.777 回答
3

这是一个简单的链接问题。在模块编译期间,OpenMP 未正确链接。因此可以加载使用 OpenMP 的 C Python 扩展。-fopenmp 必须传递给编译器,而 -lgomp 必须传递给链接器——如果您使用的是 distutils,请确保您的 setup.py 配置正确。我猜,重建 Python 也有效,因为我已经将 OpenMP 与 Python 正确链接,所以当 Python 加载模块时,库已经正确链接到。

于 2010-08-30T03:00:06.003 回答