[英]Telling GCC to *not* link libgomp so it links libiomp5 instead
[英]Linking cython code against libiomp5 instead of libgomp
是否可以使用gcc
将使用 OMP(比如“prange”语句之类的东西)的cython
代码链接到libiomp5
而不是libgomp
? 我知道有几篇文章,例如Telling GCC to *not* link libgomp so it links libiomp5 instead和其他文章,描述了如何实现这一点。 但是,它们似乎对我不起作用。 我究竟做错了什么?
具体来说,假设我使用的是最新的 Anaconda 发行版,并且有一些file.pyx
,我在上面执行cython -a file.pyx
以获取file.c
。 然后对于libgomp
我会做类似的事情
gcc -shared -pthread -fPIC -fwrapv -O3 -ffast-math -fno-strict-aliasing -march=native -fopenmp -o file.so -I/include_dirs file.c
这给了我一个file.so
。所以显示
>ldd file.so
...
libgomp.so.1 => /usr/lib64/libgomp.so.1 (0x00007fc3725ab000)
...
对于libiomp5
,通过阅读前面提到的帖子,我希望这能完成这项工作
gcc -shared -pthread -fPIC -fwrapv -O3 -ffast-math -fno-strict-aliasing -march=native -o file.so -I/include_dirs file.c -L/lib_dirs -liomp5
确实, file.so
I get 显示
>ldd *.so
...
libiomp5.so => /lib_dirs/libiomp5.so (0x00007ff92c717000)
...
但是,当我将file.so
链接到某些被迫使用特定数量的 OMP 线程的代码时,只有与file.so
链接的libgomp
版本显示使用了多个线程。 也就是说,链接到libiomp5
似乎没有错误,但系统的行为就好像一开始就没有使用 OMP pragma 一样。
PS.:我也尝试了额外的 -Wl -Wl,--as-needed
到gcc
选项(dunnowhatfor),但这并没有改变图片。
更新: - - - - - - - -
应用户vidyalatha-intel的要求,下面给出一个例子。 它没有针对最佳风格进行编码,也没有解决任何特定问题。 它只是为了允许重现问题。
A) 一些 python 代码调用*.so
库
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np
import numpy.random as rnd
import stackovfl_OMP as sc # THE lib
N = 600
# init a couple of 1d and 2d arrays
f = rnd.random(N)
e = rnd.random(N)
v = rnd.random((N,N))+1j*rnd.random((N,N))
z = np.linspace(0,3,150) + .05*1j
numthread = 4 # explicitly force 4 threads
s = []
for i in z: # for each z do stuff needing OMP in sc.sit
print(np.real(i))
s.append([np.real(i),sc.sit(i,v,e,f,numthread)])
B) lib stackovfl_OMP.so
的 cython 代码stackovfl_OMP.pyx
,做一些(相当无意义的)事情,包括三个循环,其中外部循环使用 OMP
# -*- coding: utf-8 -*-
# cython: language_level=3
cimport cython
cimport openmp
from cython.parallel import prange
import numpy as np
cimport numpy as np
@cython.cdivision(True)
@cython.boundscheck(False)
@cython.wraparound(False)
cpdef np.complex128_t sit(
np.complex128_t z,
np.ndarray[np.complex128_t,ndim=2] t,
np.ndarray[np.float64_t,ndim=1] e,
np.ndarray[np.float64_t,ndim=1] f,
np.int32_t nt # num threads
):
cdef int a,b,c,l,it
l = len(e)
''' si : Partial storage for each thread in the pool
siv : Nogil memviews for numpy array r/w access '''
cdef np.ndarray[np.complex128_t,ndim=1] si = np.zeros(nt,dtype=np.complex128)
cdef complex[:] siv = si
for a in prange(l, nogil=True, num_threads=nt): # OMP parallelization outer loop
it = openmp.omp_get_thread_num() # fixed within one thread
for b in range(l):
for c in range(l): # Do 'something'
siv[it] = siv[it] + t[c,b]*t[b,a]*t[a,c]/(2*z-e[a]+e[c])*(
(f[a]-f[b])/(z-e[a]+e[b]) + (f[c]-f[b])/(z-e[b]+e[c]))
return np.sum(si) # return collected pool
使用 A) 和 B),您可以按照原始帖子中的描述提前 go 并生成stackovfl_OMP.so
,链接到libgomp
或libiomp5
。 如那里所述,当您调用python stackovfl.py
时,只有libgomp
机器最终运行四个线程,而libiomp5
链接版本的stackovfl_OMP.so
仅保持单线程。 (另外将 OMP_NUM_THREADS=4 导出到环境中不会改变这一点。)
我在https://groups.google.com/g/cython-users/c/2niCShTH4OE的 Google cython-users 组中提到了这个问题,最终由 cython 核心开发人员 D. Woods 给出了答案。
简而言之:拆分编译和链接步骤。 在编译步骤中,您可以发出 OMP pragma。 生成的*.o
object 文件确实可以直接链接到libiomp5
。 在我给出的示例中,归结为,例如:
gcc -c -pthread -fPIC -fwrapv -O3 -ffast-math -fno-strict-aliasing -march=native -fopenmp stackovfl_OMP.c -o stackovfl_OMP.o -I/include_paths
gcc -shared -pthread -Wl,--as-needed stackovfl_OMP.o -o stackovfl_OMP.so -L/library_paths -liomp5
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/library_paths
最后, ldd
显示stackovfl_OMP.so
链接到libiomp5
并且它运行任意多的线程。 (...我在libgomp
上有任何性能差异吗...没有。)
谢谢。 D、伍兹。 功劳归功于应得的人。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.