You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 22:24:05