Numba Cuda具有syncthreads()来同步块中的所有线程。 如何在不退出当前内核的情况下同步网格中的所有块?
在C-Cuda中,有一个operativeBlocks库可以处理这种情况。我在Numba文档中找不到类似的内容。
为什么这很重要!
这种事情发生在简化中,即在每个块中计算一些东西,然后您想在这些块中找到最大值。
通常,可以将它们作为两个单独的调用推入流中。这样可以确保在调用reduce之前,块计算全部完成。
但是,如果这两个操作是轻量级的,则执行时间主要由设置内核决定,而不是由操作的执行决定。如果它们在python循环中,则可以将循环和两个kerel调用融合到一个内核中,从而轻松地使循环运行1000倍
for u in range(100000):
Amax =CudaFindArrayMaximum(A)
CudaDivideArray(A,Amax)
CudaDoSomethingWithMatrix(A)
由于循环中的三行都是快速内核,因此我想将它们和循环全部放入一个内核中。
但是,如果不跨网格中的所有块进行同步,我想不出任何办法。实际上,出于相同的原因,即使是找到最大值的第一步本身也很棘手。
答案 0 :(得分:1)
在CUDA中,不使用cooperative groups,没有安全或可靠的机制来进行网格范围的同步(除了使用内核启动边界之外)。实际上,提供这种能力是引入合作社团体的动机之一。
当前,numba不公开协作组功能。因此,目前在numba功能范围内尚无安全或可靠的方法来实现这一目标。
有关在没有合作组的情况下尝试在CUDA中进行操作的可能危害的示例,请参见this question。
答案 1 :(得分:1)
在 Numba 的 0.53.1 版本中添加了 here 支持,因此您可以通过执行以下操作来同步整个网格:
g = cuda.cg.this_grid()
g.sync()
请注意,合作组还需要
CUDA 设备运行时库 cudadevrt
可用——用于 conda 默认通道安装的 CUDA 工具包
包,它仅在 10.2 及更高版本中可用。系统安装的工具包(例如来自 NVIDIA 发行版
包或运行文件)都包含 cudadevrt。
有关详细信息,您可以阅读cooperative groups
答案 2 :(得分:0)
您可以通过全局存储器在块之间进行通信。而且,GPU以64字节之类的块读取/写入其内存。因此,如果每个块都写入一个或几个这样对齐的块,则不会发生冲突。不是同步,但至少...
但是还有另一个问题。您可以有10000个块,并且在某个时间只能工作30个:)。仅当其中一个完成并得到原谅时,下一个块才开始。但原则上,即使在这种情况下,您也可以以第一次迭代为障碍的方式组织工作,例如1-1000,下一个-1001-1500,第3个-1501-1750,依此类推。并检查每个块中是否已准备好必要的输入数据,并且在最坏的情况下进行虚拟循环...