尽管GPU加快了数学计算的速度,但将内核移至GPU进行执行的开销却是固定的。
我正在使用Cupy和numba。第一次执行使用Cupy的numpy GPU版本的函数调用时,它的速度很慢。但是第二次很快。
我意识到我不了解内核或GPU代码如何进入GPU来运行。在操作上,我想更好地理解这一点,以便我可以知道什么时候由于内核传输而使我的工作偶然地导致了一个缓慢的步骤。所以我需要一些规则或经验法则来理解这个概念。
例如,如果我将两个散布在GPU上的杯状阵列相乘,我可能会写成C = A * B
在某些时候,必须在GPU上编码*乘法的杯状重载,并且它的需求自动地也将被循环分解,从而将其分解为块和线程。因此,大概此代码是一些内核,该内核已被传输到GPU。我猜想我下次调用C * D时,不再需要学习GPU的含义,*这样就可以很快。
但是在某个时候,我想GPU需要清除旧代码,因此*或当时未使用的其他操作可能会从内存中清除掉,因此稍后再次发生对A * B的调用时,不能及时将其重新编译到GPU上。
或者我想。如果我是对的,我怎么知道这些内核何时会停留或消失?
如果我错了,这不是它的工作方式,或者还有其他缓慢的步骤(我假设数据已经传输到GPU上的阵列),那么这个缓慢的步骤是什么以及如何组织事情所以一个人付的越少越好?
我试图避免像在cuda ++中那样编写显式的numba线程管理内核,但是只使用标准的numba @ njit,@ vectorize和@stencil装饰器。同样,在Cupy中,我只想在numpy语法级别工作,而不是深入线程管理。
我已经阅读了很多关于此的文档,但它们只是指内核的开销,而不是何时获得内核以及如何控制内核的开销。
答案 0 :(得分:0)
我还没有完整的答案。但是到目前为止,我获得的最大线索来自阅读当前未记录的功能@cupy.fuse()
,这比支付内核启动成本的@numba.jit
文档更加清楚。我尚未找到@talonmies推荐的与Contexts的连接。
请参阅https://gist.github.com/unnonouno/877f314870d1e3a2f3f45d84de78d56c
关键例子是这个
c = cupy.arange(4)
#@cupy.fuse()
def foo(x):
return x+x+x+x+x
注释掉@ cupy.fuse()会导致foo(。)变慢三倍,因为每个“ +”都涉及内核加载和内核释放。 Fusion将所有添加项合并到一个内核中,因此启动和免费添加均需一次性付费。在典型的2018 GPU上,矩阵的大小不足一百万,而add()是如此之快,以至于启动和释放都是主要时间。
我希望可以在@fuse上找到一些文档。例如,它是否像@jit一样展开内部功能。我可以通过堆叠@jit和@fuse来实现吗?
但是,我仍然不清楚何时以数字货币支付费用。