繁体   English   中英

将 cython 代码链接到 libiomp5 而不是 libgomp

[英]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-neededgcc选项(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 ,链接到libgomplibiomp5 如那里所述,当您调用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM