繁体   English   中英

为什么cupy会自动将数据从GPU memory传输到CPU内存?

[英]why cupy automatically transfer data from GPU memory to CPU memory?

我正在使用 nvidia jetson nano,需要使用 cupy 及其 gpu 来加速相关性计算,并且效果很好。 但是当我调用下面的 function 并且它的第一个参数的类型是 cp.ndarray 时,它会花费很多时间; 如果它的第一个参数的类型是 np.ndarray,则代码在 flash 中完成。

def peak_search(alist, begin, end):
    res = []

    for i in range(begin + 1, end):
        loop_time_start = time.time()
        if alist[i] > alist[i - 1] and alist[i] > alist[i + 1]:
            res.append(i)
        loop_time_end = time.time()
        dTime("single loop", loop_time_start, loop_time_end)

    return res

不同类型论证的结果如下:

cp.ndarray:第一个参数的类型是 cp.ndarray

np.ndarray:第一个参数的类型是 np.ndarray

很明显主要的开销是cp.ndarray到np.ndarray的传输,但是为什么会出现在上面的function呢? 有什么办法可以避免这个成本吗?

非常感谢您的帮助。

很明显,主要成本是将 cp.ndarray 转移到 np.ndarray

当你执行alist[i] > alist[i - 1] and alist[i] > alist[i + 1]时,操作是在 GPU 上计算的,但条件是由 CPython 解释器评估的,它对 GPU 一无所知。因此CuPy 需要从 GPU 获取信息返回给 CPU,以便将其提供给 CPython。 这意味着每次迭代都会导致同步 GPU-CPU 传输通过具有非常高延迟的 PCI/NvLink 总线(与执行的计算相比)。

实际上,情况更糟:每个alist[i] > alist[i - 1]alist[i] > alist[i + 1]操作都会导致 CUDA kernel 被 CuPy 提交给 GPU。 CuPy 还需要在 GPU memory 上分配数组,这也有点昂贵。 所有这些操作都会导致非常昂贵的 kernel 调用。 假设输入是一维数组,这会导致很少的 kernel 调用,CUDA kernel 提交,PCI/Nvlink 传输每个元素至少持续数百微秒,以便在 CPU 可以在(小于)几纳秒内计算的标量上运行(所以它比应该的速度慢 >= 100_000 倍)。

有什么办法可以避免这个成本吗?

你永远不应该在 GPU 上计算标量项,甚至是小的 arrays(除非每个项的计算量真的很大)。 您需要编写连续处理大量项目的内核(理想情况下是 1 CUDA 内核)。 事实上,就性能而言,CuPy 的工作方式与 Numpy 完全一样:您应该调用矢量化函数。

我认为您应该首先编写优化的 Numpy 代码,然后尝试将 GPU 与 CuPy 一起使用。 或者,您可以尝试直接编写 CUDA kernel ,但这是非常低级的,因此更难做到。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM