我在一台8核处理器的机器上工作,使用的是8G内存和Linux Redhat 7,我使用的是Pycharm IDE。
我尝试使用python线程模块来利用多核处理的优势,但最终得到的代码要慢得多。我通过Numba发布了GIL,并确保我的线程正在进行足够复杂的计算,因此问题不是在例如How to make numba @jit use all cpu cores (parallelize numba @jit)中讨论的问题
下面是多线程代码:
l=200
@nb.jit('void(f8[:],f8,i4,f8[:])',nopython=True,nogil=True)
def force(r,ri,i,F):
sum=0
for j in range(12):
if (j != i):
fij=-4 * (12*1**12/(r[j]-ri)**13-6*1**6/(r[j]-ri)**7)
sum=sum+fij
F[i+12]=sum
def ODEfunction(r, t):
f = np.zeros(2 * 12)
lbound=-4* (12*1**12/(-0.5*l-r[0])**13-6*1**6/(-0.5*l-r[0])**7)
rbound=-4* (12*1**12/(0.5*l-r[12-1])**13-6*1**6/(0.5*l-r[12-1])**7)
f[0:12]=r[12:2*12]
thlist=[threading.Thread(target=force, args=(r,r[i],i,f)) for i in range(12)]
for thread in thlist:
thread.start()
for thread in thlist:
thread.join()
f[12]=f[12]+lbound
f[2*12-1]=f[2*12-1]+rbound
return f这是顺序版本:
l=200
@nb.autojit()
def ODEfunction(r, t):
f = np.zeros(2 * 12)
lbound=-4* (12*1**12/(-0.5*l-r[0])**13-6*1**6/(-0.5*l-r[0])**7)
rbound=-4* (12*1**12/(0.5*l-r[12-1])**13-6*1**6/(0.5*l-r[12-1])**7)
f[0:12]=r[12:2*12]
for i in range(12):
fi = 0.0
for j in range(12):
if (j!=i):
fij = -4 * (12*1**12/(r[j]-r[i])**13-6*1**6/(r[j]-r[i])**7)
fi = fi + fij
f[i+12]=fi
f[12]=f[12]+lbound
f[2*12-1]=f[2*12-1]+rbound
return f我还想在多线程和顺序代码运行期间附加一个系统监视器的图像:
System Motinor during the run of the multi threaded code
System Motinor during the run of the sequential code
有人知道线程化代码效率低下的原因是什么吗?
发布于 2018-06-21 00:31:17
你必须意识到,在Python中调用一个函数是非常昂贵的(例如,与在C中调用一个函数相比),甚至调用一个numba-jitted函数:必须检查参数是否正确(例如,它们确实是你正在传递的浮点数组-我们将看到它可能比普通的Python调用慢5倍)。
让我们来检查一下Let函数的开销,与函数中发生的工作相比:
import numba as nb
import numpy as np
@nb.jit('void(f8[:],f8,i4,f8[:])',nopython=True,nogil=True)
def force(r,ri,i,F):
sum=0
for j in range(12):
if (j != i):
fij=-4 * (12*1**12/(r[j]-ri)**13-6*1**6/(r[j]-ri)**7)
sum=sum+fij
F[i+12]=sum
@nb.jit('void(f8[:],f8,i4,f8[:])',nopython=True,nogil=True)
def nothing(r,ri,i,F):
pass
def no_jit(r,ri,i,F):
pass
F=np.zeros(24)
r=np.zeros(12)现在:
>>>%timeit force(r,1.0,0,F)
706 ns ± 8.96 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
>>>%timeit nothing(r,1.0,0,F)
645 ns ± 5.36 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
>>>%timeit no_jit(r,1.0,0,F) #to measure overhead of numba
120 ns ± 6.56 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)所以基本上有90%的开销,这在单线程模式下是没有的,因为函数是“内联”的。这并不奇怪:您的for循环只有12次迭代-这是不够的,例如,在示例中,您链接的内部循环有10^10迭代!
此外,在线程之间分派工作也会产生一些开销,我的直觉是它甚至比jitted call的开销还要多-但为了确保人们应该分析程序。即使有8个内核,这些赔率也很难被击败!
与花费在函数本身上的时间相比,现在最大的拦路虎可能是force-call的巨大开销。上面的分析非常肤浅,所以我不能保证没有其他重要的问题--但让force有更多的工作将是朝着正确方向迈出的一步。
https://stackoverflow.com/questions/50938382
复制相似问题