Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Mxnet-将阵列缓慢复制到GPU_Python_Performance_Gpu_Mxnet - Fatal编程技术网

Python Mxnet-将阵列缓慢复制到GPU

Python Mxnet-将阵列缓慢复制到GPU,python,performance,gpu,mxnet,Python,Performance,Gpu,Mxnet,我的问题是:如何在mxnet中执行快速矩阵乘法 我的具体问题是:阵列复制到GPU的速度很慢。对此我们能做些什么 我创建随机数组,将它们复制到上下文中,然后进行乘法 import mxnet as mx import mxnet.ndarray as nd from mxnet import profiler profiler.set_config(aggregate_stats=True) ctx = mx.cpu() # create arrays on CPU profiler.se

我的问题是:如何在mxnet中执行快速矩阵乘法

我的具体问题是:阵列复制到GPU的速度很慢。对此我们能做些什么

我创建随机数组,将它们复制到上下文中,然后进行乘法

import mxnet as mx
import mxnet.ndarray as nd

from mxnet import profiler

profiler.set_config(aggregate_stats=True)

ctx = mx.cpu()

# create arrays on CPU
profiler.set_state('run')
a = nd.random.uniform(-1, 1, shape=(10000, 10000), ctx=mx.cpu())
b = nd.random.uniform(-1, 1, shape=(10000, 10000), ctx=mx.cpu())
nd.waitall()
profiler.set_state('stop')
print(profiler.dumps(reset=True))

# copy arrays to the context
profiler.set_state('run')
a_ctx = a.as_in_context(ctx)
b_ctx = b.as_in_context(ctx)
nd.waitall()
profiler.set_state('stop')
print(profiler.dumps(reset=True))

# multiply arrays
profiler.set_state('run')
c = nd.dot(a_ctx, b_ctx)
nd.waitall()
profiler.set_state('stop')
print(profiler.dumps(reset=True))
在这段代码中,我在cpu上执行所有操作,因此我的时间是(秒):

当我使用
ctx=mx.gpu()
时,时间是

 0.247
22.059
 0.828
因此,瓶颈是从CPU到GPU的拷贝。它只是慢得可笑。对此我们能做些什么

这是有关此阶段的准确信息:

Device Storage
=================
Name                          Total Count        Time (ms)    Min Time (ms)    Max Time (ms)    Avg Time (ms)
----                          -----------        ---------    -------------    -------------    -------------
Memory: gpu/0                           2      400000.0000      400000.0000      800000.0000      200000.0000

MXNET_C_API
=================
Name                          Total Count        Time (ms)    Min Time (ms)    Max Time (ms)    Avg Time (ms)
----                          -----------        ---------    -------------    -------------    -------------
MXImperativeInvokeEx                    2       22059.0703           0.0360       22059.0352       11029.5352
MXNDArrayGetShape                       2           0.0030           0.0000           0.0030           0.0015
MXNDArrayWaitAll                        1         105.9830         105.9830         105.9830         105.9830
MXNDArrayCreateEx                       2           0.0150           0.0060           0.0090           0.0075
MXNDArrayGetContext                     2           0.0020           0.0000           0.0020           0.0010
MXNet C API Concurrency                22           0.0000           0.0000           0.0010           0.0005
MXNDArrayGetDType                       2           0.0010           0.0000           0.0010           0.0005
MXNet C API Calls                      11           0.0140           0.0040           0.0140           0.0050

operator
=================
Name                          Total Count        Time (ms)    Min Time (ms)    Max Time (ms)    Avg Time (ms)
----                          -----------        ---------    -------------    -------------    -------------
CopyCPU2GPU                             4         318.4930          53.3060         105.9400          79.6233

如果需要更多信息,请告诉我。

您可以从分析结果中看到,
CopyCPU2GPU
只需318ms。额外的22秒开销与GPU上下文初始化和malloc有关。如果您只是在同一个脚本中再次运行GPU复制代码,您应该会看到更快的结果。您可以这样修改代码:

# copy arrays to the context
a_ctx = a.as_in_context(ctx)
b_ctx = b.as_in_context(ctx)
nd.waitall()
profiler.set_state('run')
a_ctx = a.as_in_context(ctx)
b_ctx = b.as_in_context(ctx)
nd.waitall()
profiler.set_state('stop')
print(profiler.dumps(reset=True))

另一个要考虑的是尽量减少CPU -> GPU内存拷贝。例如,在您的特定示例中,您可以在GPU而不是CPU中创建随机阵列:

a = nd.random.uniform(-1, 1, shape=(10000, 10000), ctx=ctx)
b = nd.random.uniform(-1, 1, shape=(10000, 10000), ctx=ctx)
CUDA内存分配/释放需要一些系统同步,这会使其速度变慢。所有DL framworks都自己进行内存管理,但创建一个缓冲池来重用以前分配的缓冲区,并仅在绝对必要时进行内存分配/释放。例如,默认情况下,tensorflow在单个分配中分配整个GPU内存,并在内部将其分配给Tensor。MXNet和PyTorch在必要时进行分配,但在释放时保留在缓冲池中,以便以后可以重用


MXNet/PyTorch的这种行为意味着,在第一次调用创建特定大小的张量时,调用速度会变慢。但是,如果释放该张量并创建一个类似大小的新张量,那么这次内存来自预分配的缓冲池,而不是使用cudamaloc。您可以在此处阅读PyTorch的内存管理(),它有点类似于MXNet。

谢谢!这似乎确实是一个初始化过程:即使我只是执行
nd.random.uniform(-1,1,shape=(1,1),ctx=ctx)
在一开始,其他一切都运行得很快。你知道,有没有办法缩短初始化时间?我认为这是不可能的,但以防万一。我相信延迟的一个重要部分就是唤醒并初始化英伟达驱动程序,你可以用它来修复。其余的延迟与cuda malloc有关,每次跑步时都会发生。谢谢!你所说的与cuda malloc相关的延迟是什么意思?我在哪里可以读到它?更新了上面的答案。
a = nd.random.uniform(-1, 1, shape=(10000, 10000), ctx=ctx)
b = nd.random.uniform(-1, 1, shape=(10000, 10000), ctx=ctx)