python - Numba CUDA 加速似乎很低
问题描述
新手从 Numba/cuda 开始。我写了这个小测试脚本来比较@jit 和@cuda.jit。速度,只是为了感受一下。它为 256 个单独的实例计算逻辑方程的 10M 步。cuda 部分大约需要 1.2 秒才能完成。cpu 'jitted' 部分在接近 5 秒内完成(cpu 上只使用了一个线程)。因此,从 GPU(专用 GTX1080TI 不做任何其他事情)开始,大约有 4 倍的加速。我预计并行处理所有 256 个实例的 cuda 部分会快得多。我究竟做错了什么?
这是工作示例:
#!/usr/bin/python3
#logistic equation on gpu/cpu comparison
import os,sys
#Set environment variables (needed for numba 0.42 to find lvvm)
os.environ['NUMBAPRO_NVVM'] = '/usr/lib/x86_64-linux-gnu/libnvvm.so'
os.environ['NUMBAPRO_LIBDEVICE'] = '/usr/lib/nvidia-cuda-toolkit/libdevice/'
from time import time
from scipy import *
from numba import cuda, jit
from numba import int64,int32, float64
@cuda.jit
def logistic_cuda(array_in,array_out):
pos = cuda.grid(1)
x = array_in[pos]
for k in range(10*1000*1000):
x = 3.9 * x * (1 - x)
array_out[pos] = x
@jit
def logistic_cpu(array_in,array_out):
for pos,x in enumerate(array_in):
for k in range(10*1000*1000):
x = 3.9 * x * (1 - x)
array_out[pos] = x
if __name__ == '__main__':
N=256
in_ary = random.uniform(low=0.2,high=0.9,size=N).astype('float32')
out_ary = zeros(N,dtype='float32')
t0 = time()
#explicit copying. not really needed
d_in_ary = cuda.to_device(in_ary)
d_out_ary = cuda.to_device(out_ary)
t1 = time()
logistic_cuda[1,N](d_in_ary,d_out_ary)
cuda.synchronize()
t2 = time()
out_ary = d_out_ary.copy_to_host()
t3 = time()
print(out_ary)
print('Total time cuda: %g seconds.'%(t3-t0))
out_ary2 = zeros(N)
t4 = time()
logistic_cpu(in_ary,out_ary2)
t5 = time()
print('Total time cpu: %g seconds.'%(t5-t4))
print('\nDifference:')
print(out_ary2-out_ary)
#Total time cuda: 1.19364 seconds.
#Total time cpu: 5.01788 seconds.
谢谢!
解决方案
问题可能来自于非常少量的数据和循环依赖。事实上,由于大量的 CUDA 内核,现代 Nvidia GPU 可以同时执行数千个 CUDA 线程(打包成 32 个线程)。array_out
在您的情况下,每个线程在使用顺序循环的一个单元上执行计算。但是,只有 256 个单元格。因此,最多可以同时运行 256 个线程(8 个 warp)——这只是您的 GPU 应该能够管理的并发线程数量的一小部分。因此,如果您想要更好的加速,您需要为 GPU 提供更多的并行性(例如通过增加数据大小或同时计算多重回归)。