运行 使用 numba 和 cupy 在单个 GPU 上并行执行多个 GPU 函数

Run multiple GPU functions on a single GPU in parallel using numba and cupy

我想知道在同一代码中并行 运行 多个 cupy 函数或 numba cuda 内核是否可能甚至安全。目前我的代码是这样做的:

for i in range(int(nLoop)):
        #shuffle the array
        cp.random.shuffle(temp)
        temp1,temp2 = cp.split(temp,2)
        #configure number of blocks for cuda kernels
        blocks = 0
        Ti = cp.zeros(len(temp1))
        if(len(temp1) >= len(temp2)):
            blocks = int(math.ceil(len(temp1)/tpb))
        else:
            blocks = int(math.ceil(len(temp2)/tpb))
            
        Ti = myCalculations(temp1,temp2) #function that executes some numba cuda kernels
        results[i] = Ti

我想做的是将这个 for 循环拆分成更多的 for 循环,例如并行 10 个循环 运行ning,可能使用 prange。这可能吗(当然考虑到我需要制作临时列表来存储结果等)?

就 GPU 内存而言,在 16GB 的典型使用中,它占用了大约 600MB,所以我看不出这里有什么问题。

It is possible or even safe to run multiple cupy functions or numba cuda kernels in parallel inside the same code.

这样做不是个好主意。事实上,有两种主要的方法可以并行 运行 一个 CPython 代码。第一个,多线程,由于 GIL(全局解释器锁),应该是安全的,但由于 GIL,它也非常低效,因为它将阻止任何 Cupy 调用并行 运行,除非它们释放 GIL(这当然现在还不是这样)。对于第二个,多处理,fork 将导致初始化过程缓慢(CUDA 运行time 初始化,Numba 函数可能会重新编译或从缓存中获取等),并且您将需要在多个进程之间共享 GPU 数据处理过程有点棘手,因为您需要使用 Cupy 的 CUDA 运行time IPC 函数(有关更多信息,请参阅 ipcOpenMemHandle for example). In both case, the low-level CUDA function calls will certainly be executed serially (it was the case the last time I tried with a multithreaded application). Moreover, running multiple CUDA kernels in parallel generally does not make them (much) faster because the GPU already execute kernel in parallel. In fact, in multithreaded application, they will always run serially unless you use multiple streams, and even if you do use multiple stream this will generally not be significantly faster in most case. See this post。您不能在 Numba 代码(尤其是并行代码)中使用 Cupy。

这个问题的一般解决方案是编写自己的内核,直接在整个数据集上运行。这通常比 运行 宁许多小内核更有效,但它也可能更复杂。不幸的是,这就是 GPU 的工作方式。

请注意,如果您的循环迭代是完全独立的,那么您可以在顺序过程中使用多个流,这样 CUDA 运行time 可以通过减少(不需要的)慢速同步的数量来更好地使用 GPU。