使用CuPy时GPU到CPU数据传输速度极慢问题求助
问题根因分析
- CuPy所有CUDA操作默认是异步执行的,调用
convolve后代码立刻向下运行不代表卷积运算已经完成,只是任务被提交到了CUDA流队列排队执行。 - 你的计时逻辑将卷积的实际执行时间全部统计到了后续
cp.asnumpy()操作的耗时中,才会出现「回拷耗时数百秒」的错觉:因为cp.asnumpy()是同步操作,触发时会等待CUDA流中所有未完成的任务(包括前面的卷积运算)全部执行完成后,才会开始数据传输。 - 你对比的PyTorch、TensorFlow在调用张量转CPU数组接口时,框架内部会自动等待前置运算完成,因此不会出现时间统计错位的问题。
验证方法
使用如下代码拆分统计卷积运算和数据回拷的实际耗时:
import cupy as cp from cupyx.scipy.ndimage import convolve import numpy as np xt = np.random.randint(0, 255, (20, 256, 256)).astype(np.float32) xt_gpu = cp.asarray(xt) # 预热操作,避免 CUDA 初始化开销影响统计 _ = convolve(xt_gpu, xt_gpu, mode='constant') cp.cuda.synchronize() # 统计卷积实际耗时 start_conv = cp.cuda.Event() end_conv = cp.cuda.Event() start_conv.record() result_gpu = convolve(xt_gpu, xt_gpu, mode='constant') end_conv.record() end_conv.synchronize() print(f"卷积运算耗时: {cp.cuda.get_elapsed_time(start_conv, end_conv)/1000:.2f}s") # 统计回拷实际耗时 start_trans = cp.cuda.Event() end_trans = cp.cuda.Event() start_trans.record() result_cpu = cp.asnumpy(result_gpu) end_trans.record() end_trans.synchronize() print(f"GPU到CPU回拷耗时: {cp.cuda.get_elapsed_time(start_trans, end_trans)/1000:.4f}s")
运行后可观测到:20×256×256的float32数组总大小仅5MB左右,正常PCIE通道回拷耗时不会超过1ms,数百秒的耗时实际全部来自三维卷积运算。
优化建议
- 如果确认卷积运算耗时不符合预期,可以检查CuPy版本、CUDA驱动与你使用的GPU型号是否适配,也可以更换为
cupyx.scipy.signal.convolve等其他卷积实现尝试提速。 - 如果需要手动控制异步逻辑,可以显式调用
cp.cuda.synchronize()同步当前CUDA流的所有待执行任务。
内容的提问来源于stack exchange,提问作者anki
相关产品推荐
相关产品推荐

