设置 Pythran 以在 Windows 上使用 clang-cl.exe 和 OpenMP 工作进行编译:需要一种传递编译器参数的方法

Setting up Pythran for compiling on Windows with clang-cl.exe and OpenMP working: need a way to pass compiler arguments

我正在使用 Pythran 将 Python 代码编译成 C/C++,并在 Windows 上支持 OpenMP。现在文档对​​ Windows 不是很好 - 它指出: “Windows 支持正在进行中,仅针对 Python 3.5+ 和 Visual Studio 2017 或更好的 clang-cl。请注意,使用 clang-cl.exe 是默认设置.可以通过CXX和CC环境变量改变."

我发现你必须使用

否则代码将无法编译(MSVC 不喜欢它)。

因此首选编译器是 clang-cl.exe,它是 cl.exe 的“直接”替代品,因此通过选择“C++ Clang tools for Windows," 现在我有 C:\Program Files (x86)\Microsoft Visual Studio19\BuildTools\VC\Tools\Llvm\x64\bin\clang-cl.exe 以及 LLVM 链接器 lld-link.exe - 因为 clang-cl.exe 是默认设置,我不需要更改任何设置文件,我只是运行 vcvarsall.bat before Pythran 所以编译器目录在路径中。 (我后来注意到要让 lld-link.exe 使用一些 distutils _msvccompiler.py 的黑客攻击是必需的,将 link.exe 切换到 lld-link.exe 并注释掉 '/LTCG' 标志,因为 Clang 没有'有那个选项,那么它就可以工作......但仍然没有 OpenMP......

我在 Anaconda 中使用虚拟环境编译了其中一个示例,其中 pip 安装了 NumPy 和 SciPy 库(OpenBLAS 后端),因为几乎没有记录 MKL 支持。它需要 pythran-openblas 包,所以我也 pip 安装了它,并且它用 clang-cl 编译得很好,我可以毫无问题地导入它。我发现 [Python]\Lib\site-packages\pythran\pythran-win32.cfg 有一个选项可以传递 cflags ,我可以在其中键入正确的编译器参数,例如: -Xclang -fopenmp -march=ivybridge 和 运行ning pythran [script.py],所有这些标志都以正确的方式传递(使用默认值是不正确的)。但是......文档中的这个例子仍然没有运行并行。

我在 Stack Exchange 上发现:clang-cl -cc1 --help 会输出 clang 可以处理的所有参数。在 openmp 下,它指出:-fopenmp 解析 OpenMP 编译指示并生成并行代码。所以我的猜测是 Pythran 文档中给出的示例没有 OpenMP pragmas 可以并行。现在他们为什么要那样做?不知道,因为他们展示了一个通过 OpenMP 使它变得非常快的例子,但我无法在 Windows 上重现它。我有 6 个核心/12 个虚拟,所以我应该看到加速。

还有其他人有我可以试用的另一个 OpenMP 示例吗???还是以另一种方式解开了使用 OpenMP 的谜团?

非常感谢!

Pythran 项目维护者在我直接给他发邮件后回复了我。似乎 OpenMP 仅通过显式 #omp 语句受支持。因此,前段时间当他们编写文档时,它会推断出并行例程,但现在不会。因此,要将示例转换为 OpenMP,需要进行一些更改:

#pythran export arc_distance(float[], float[], float[], float[])
import numpy as np
def arc_distance(theta_1, phi_1, theta_2, phi_2):
"""
Calculates the pairwise arc distance
between all points in vector a and b.
"""
    size = theta_1.size
    distance_matrix=np.empty_like(theta_1)
    #omp parallel for
    for i in range(size):
        temp = (np.sin((theta_2[i]-theta_1[i])/2)**2 + np.cos(theta_1[i])*np.cos(theta_2[i]) * np.sin((phi_2[i]-phi_1[i])/2)**2)
        distance_matrix[i] = 2 * np.arctan2(np.sqrt(temp), np.sqrt(1-temp))
    return distance_matrix

但是...还有其他未记录的编译器参数需要传递才能使 OpenBLAS-backed OpenMP 模块正常工作,这花了我几个小时才弄清楚。他们在这里:

Pythran OpenBLAS Windows 10 个设置:

找到文件[Python]\Lib\site-packages\pythran\pythran-win32.cfg

添加到 library_dirs:'C:\Program Files (x86)\Microsoft Visual Studio19\BuildTools\VC\Tools\Llvm\x64\lib'

添加到 cflags:-Xclang -fopenmp

添加到 ldflags:\libiomp5md.lib

将 blas 设置为:blas=pythran-openblas

然后它应该可以正常编译:pythran -v arc_distance.py - 添加 -v 标志对于发现问题非常有帮助(详细编译器模式),但不需要。

Pythran Intel MKL Windows 10 个设置(Anaconda3 默认库): 我还决定为什么不尝试在 NumPy 和 SciPy 等都是用 MKL 编译的默认 Anaconda3 上进行这项工作?我的公司使用 Anaconda3,所以每个人都已经有了 Intel MKL。和 OpenBLAS 设置一样,Windows 的 MKL 设置也没有记录。所以我想通了:

找到文件 [Python]\Lib\site-packages\pythran\pythran-win32.cfg,(很可能在 C:\Users[用户名]\Anaconda3)

添加到include_dirs='C:\Program Files (x86)\Microsoft Visual Studio19\BuildTools\VC\Tools\Llvm\x64\lib', '[Python]\Library\include'

添加到 cflags:-Xclang -fopenmp

添加到 ldflags:\libomp.lib

将 blas 设置为:blas=mkl

现在您会注意到与 OpenBLAS 设置相比上面的一些奇怪的事情。没有填充库路径,而是必须在包含路径中(不要问为什么,我不知道)。 OpenMP 库也不同。同样,我不知道为什么与 OpenBLAS 一起工作的那个拒绝与英特尔 MKL 一起工作。但无论如何,这将为您提供基于 Intel MKL 的系统上带有 OpenMP 的 Pythran。