如何指示 CuPy 在 GPU 中同时运行多个相同的作业?
Posted
技术标签:
【中文标题】如何指示 CuPy 在 GPU 中同时运行多个相同的作业?【英文标题】:How to instruct CuPy to run multiple number of the same job concurrently in a GPU? 【发布时间】:2020-09-01 17:33:30 【问题描述】:下面是一个名为 job()
的简单函数,它在 GPU 中执行多个 CuPy 任务。
我如何指示 CuPy 并发运行 job()
一百万次,然后汇总它们的结果?
我的问题的目的是了解如何通过 CuPy 将多个并发作业提交到一个 GPU。
测试脚本
import numpy as np
import cupy as cp
def job( nsamples ):
# Do some CuPy tasks in GPU
d_a = cp.random.randn( nsamples )
d_b = cp.random.randint( -3, high=3, size=nsamples )
d_result = ( d_a + d_b )
d_hist, _ = cp.histogram( d_result, bins=cp.array([-3,-2,-1,0,1,2,3,4]) )
std = cp.std( d_hist )
return std
# Perform 1 job in GPU
nsamples = 10 #can be as large as tens to hundreds of thousands
std = job( nsamples, 0 )
print( 'std', std, type(std) )
更新:
# Create Cuda streams
d_streams = []
for i in range(0, 10):
d_streams.append( cp.cuda.stream.Stream( non_blocking=True ) )
# Perform Concurrent jobs via Cuda Stream.
results = []
for stream in d_streams:
with stream:
results.append( job( nsamples ) )
print( 'results', results, len(results), type(std) )
在阅读了Nvidia developer blog on Cuda Stream、Support CUDA stream with stream memory pool 上的这个 CuPy 问题和CuPy Concurrency 上的这个 SOF 问题之后,我尝试了上述方法,这似乎有效。但是,我不知道如何查看作业是同时运行还是串行运行。
问题:
如何分析 Cupy 在 GPU 中执行作业的情况,以评估我的脚本是否在执行我想要的操作?答:nvprof --print-gpu-trace python filename.py
我可以发布的数字流是否有限制(例如,受某些硬件限制)还是“无限”?
【问题讨论】:
您正在考虑并行任务。您希望数据并行化。 @RobertCrovella 您能否详细说明或向我介绍您的意思的文档。干杯。 【参考方案1】:我的一般建议是将所有数据连接在一起(跨作业),并寻求以数据并行方式完成工作。这是一个粗略的例子:
$ cat t34.py
import numpy as np
import cupy as cp
def job( nsamples, njobs ):
# Do some CuPy tasks in GPU
d_a = cp.random.randn( nsamples, njobs )
d_b = cp.random.randint( -3, high=3, size=(nsamples, njobs) )
d_result = ( d_a + d_b )
mybins = cp.array([-3,-2,-1,0,1,2,3,4])
d_hist = cp.zeros((njobs,mybins.shape[0]-1))
for i in range(njobs):
d_hist[i,:], _ = cp.histogram( d_result[i,:], bins=mybins )
std = cp.std( d_hist, axis=1 )
return std
nsamples = 10 #can be as large as tens to hundreds of thousands
std = job( nsamples, 2 )
print( 'std', std, type(std) )
$ python t34.py
std [0.69985421 0.45175395] <class 'cupy.core.core.ndarray'>
$
对于job
中的大多数操作,我们可以执行适当的cupy
操作来处理所有作业的工作。举一个例子,std
函数可以很容易地扩展到在所有作业中执行其工作。 histogram
是个例外,因为 numpy 或 cupy 中的例程不允许分区/分段算法,我可以看到。所以我为此使用了一个循环。如果这是您想要做的实际工作,则可以将分区直方图 cupy 例程编写为cupy kernel。另一种选择是在流中只发布cupy直方图。
【讨论】:
哇!这太棒了。因此,只需在每个ndarray
对象中添加另一个轴或维度来表示“njobs”,我就可以简洁地表达我需要做的事情并更好地利用ndarray
对象的强大功能。我需要时间来消化你对直方图的解释的第二部分。每个轴的大小有限制吗?怎么确定?我确实需要在结果的一个轴上获得直方图。你能给我举个例子,说明如何将分区直方图-cupy-例程编写为cupy内核或在流中发出cupy直方图吗?我想学那个。谢谢。
我不知道轴尺寸的一般限制。我通常会从 GPU 上的内存开始定义数组的上限。我不知道有关编写 Cupy 内核直方图例程的教程。我会尝试学习这些东西:1.如何在CUDA中编写直方图,例如here 2.如何在CUDA中编写分段算法3.如何编写cupy kernel然后结合所有这些知识。
以上是关于如何指示 CuPy 在 GPU 中同时运行多个相同的作业?的主要内容,如果未能解决你的问题,请参考以下文章
为啥同时使用 numba.cuda 和 CuPy 从 GPU 传输数据这么慢?