Python cuda延迟?

2024-10-06 12:35:14 发布

您现在位置:Python中文网/ 问答频道 /正文

有了各种支持GPU编程的库,我发现我在GPU和CPU上的算法性能更差。我相信这是由于两个设备之间的通信延迟造成的。在

我的平台是W10x64,i7-7700HQ和gtx1050安装在戴尔xps15笔记本电脑上。在

如果我使用任何库,例如pytorch.cuda.FloatTensor,或者cupy.ndarray触摸GPU数组,似乎需要大约20~40us。以下是MWE:

import cupy as cu

ary = cu.empty((1))
const_one = cu.ones((1))

%timeit ary + const_one
> 18.5 µs ± 102 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

在一个元素上操作并不是GPU的用途,这是一个人为的例子,它显示了两个数据段(都驻留在GPU上)的最小操作时间。在

我相信cuda代码的结构是在GPU有能力的情况下建立并消耗一个操作队列,所以这种延迟会随着时间的推移而消失,还是会随着内存块的增大而消失?在

这里是numpy和cupy中相同算法的完整比较,后者在128x128光学瞳孔上以双精度完成相位误差,并使用它创建点扩展函数。在

我已经尽可能小心地减少主机设备传输;对于cupy来说,CPU上只存在数组大小的int,因为我无法提前在GPU上获得它们。在

初始设置:

^{pr2}$

CUDA执行

%%timeit
x = cu.linspace(-cu1, cu1, ary_size, dtype=precision)
y = cu.linspace(-cu1, cu1, ary_size, dtype=precision)
xx, yy = cu.meshgrid(x, y)
rho, phi = cu.sqrt(xx**cu2 + yy**cu2), cu.arctan2(yy, xx)
phase_err = rho ** cu2 * cu.cos(phi)
mask = rho > cu1
wv_ary = cu.exp(1j * cu2 * np.pi * phase_err)
wv_ary[mask] = cu0
padded = cu.pad(wv_ary, ((pad, pad), (pad, pad)), mode='constant', constant_values=0)
psf = fftshift(fft2(ifftshift(padded)))
intensity_psf = abs(psf)**cu2
> 4.73 ms ± 86.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Numpy等价物:

%%timeit
x = np.linspace(-1, 1, ary_size, dtype=precision)
y = np.linspace(-1, 1, ary_size, dtype=precision)
xx, yy = np.meshgrid(x, y)
rho, phi = np.sqrt(xx**2 + yy**2), np.arctan2(yy, xx)
phase_err = rho ** 2 * np.cos(phi)
mask = rho > 1
wv_ary = np.exp(1j * 2 * np.pi * phase_err)
wv_ary[mask] = 0
padded = np.pad(wv_ary, ((pad, pad), (pad, pad)), mode='constant', constant_values=0)
psf = nfftshift(nfft2(nifftshift(padded)))
intensity_psf = abs(psf)**2
> 7.29 ms ± 63.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

所以我用cuda只能得到35%的性能提升。我知道我没有特别强大的GPU,它的fp64比fp32的性能差得多;但是重复使用f32精度并不能显著提高速度。在

我还知道,如果我将大小更改为更大的值,例如512,CUDA将更好地显示GPU性能,GPU的时间为8.19ms,CPU的时间为144ms。在

所以看起来这个GPU-CPU协调延迟是我在小阵列规模下的致命伤。这是我笔记本电脑的怪癖吗?很难找到CPU-GPU延迟的信息,但有一些报告显示PCI-E延迟小于1us。如果是这样的话,那么我的cuda代码将以20倍的速度运行,并且更易于使用。在


Tags: gpunpcpu性能cudaxxpadrho
1条回答
网友
1楼 · 发布于 2024-10-06 12:35:14

似乎所有的操作都是内存限制的,可能除了exp和atan在GPU上是双精度的。根据GeForce website,GPU的内存带宽似乎是112GB/s。根据ark.intel.com,您的CPU可能有大约37GB/s的带宽。那是x4。在

请注意,小数据集确实适合CPU的二级缓存,因此可以假设写操作之后的读操作在缓存中(比dram快一个数量级)。可以玩x2。在

最后,当在GPU上启动这样的操作时,问题的大小不足以让GPU隐藏延迟,因此您无法获得完整的带宽:读取的成本比其延迟比吞吐量更接近于它。如果你填充了一半的读总线,你就得到了一半的带宽。在

所有这些都可以通过验证或者不用NV prof来分析你的代码,然后你应该看到单个内核的计时和延迟。在

相关问题 更多 >