为什么在 Matlab 中 gpuArray 的 repmat 和 reshape 这么慢?
Why repmat and reshape so slow for gpuArray in Matlab?
我当前的任务是使用 gpu 同时训练多个网络。我现在做不到,所以现在我尝试对数组进行一些操作。
a = rand(1000, 1000, 'gpuArray');
tic; for i = 1 : 100 a .* a; end; toc; % line 1
tic; for i = 1 : 100 repmat(a, 3, 10); end; toc; % line 2
tic; for i = 1 : 100 reshape(a, 10, 10000); end; toc; % line 3
b = rand(1000, 1000);
tic; for i = 1 : 100 b .* b; end; toc; % line 4
tic; for i = 1 : 100 repmat(b, 3, 10); end; toc; % line 5
tic; for i = 1 : 100 reshape(b, 10, 10000); end; toc; % line 6
所以 line 1
比 line 4
更假但是
line 2
比 line 5
慢并且
line 3
比 line 6
慢
对于具有其他大小的许多其他数组,对于 repmat
和 reshape
,可以看到比 CPU 更快的 GPU。
有人可以解释我应该怎么做才能获得预期的加速吗?
如果您看到任何令人惊讶的东西,那么您看到的只是异步执行。 a .* a
没有实际做任何事情就退出了,它只是设置了 GPU 上的计算。因此,您所计时的只是排队执行 100 个内核所花费的时间。您需要使用 gputimeit
或 wait(gpuDevice)
在您的代码中获得正确的计时。也许在 repmat
执行时达到了队列限制,因此 MATLAB 被迫等待一些乘法发生,但我不能确定。
a = rand(1000, 1000, 'gpuArray');
b = gather(a);
fprintf('Times for @times: ');
fprintf('GPU: %f secs ', gputimeit(@()a.*a));
fprintf('CPU: %f secs\n', timeit(@()b.*b));
fprintf('Times for @repmat: ');
fprintf('GPU: %f secs ', gputimeit(@()repmat(a,3,10)));
fprintf('CPU: %f secs\n', timeit(@()repmat(b,3,10)));
fprintf('Times for @reshape: ');
fprintf('GPU: %f secs ', gputimeit(@()reshape(a,10,100000)));
fprintf('CPU: %f secs\n', timeit(@()reshape(b,10,100000)));
并且输出:
Times for @times: GPU: 0.000382 secs CPU: 0.001642 secs
Times for @repmat: GPU: 0.005186 secs CPU: 0.032809 secs
Times for @reshape: GPU: 0.000053 secs CPU: 0.000002 secs
reshape
在 CPU 上可能真的更快(尽管它在噪音中下降),因为在对象上调用方法比直接检查或修改数组的属性花费更长的时间。但实际上,它是如此之快以至于对于任何真正的 GPU 应用程序都不重要。
如果您在设备上没有得到类似的数字,那么毫无疑问这与您的 GPU 质量有关。 repmat
是一种高内存带宽功能 - 也许您的游戏卡或笔记本电脑芯片对双精度阵列的性能很差?您可以在 single
尝试一下,看看情况是否有所改善。
我当前的任务是使用 gpu 同时训练多个网络。我现在做不到,所以现在我尝试对数组进行一些操作。
a = rand(1000, 1000, 'gpuArray');
tic; for i = 1 : 100 a .* a; end; toc; % line 1
tic; for i = 1 : 100 repmat(a, 3, 10); end; toc; % line 2
tic; for i = 1 : 100 reshape(a, 10, 10000); end; toc; % line 3
b = rand(1000, 1000);
tic; for i = 1 : 100 b .* b; end; toc; % line 4
tic; for i = 1 : 100 repmat(b, 3, 10); end; toc; % line 5
tic; for i = 1 : 100 reshape(b, 10, 10000); end; toc; % line 6
所以 line 1
比 line 4
更假但是
line 2
比 line 5
慢并且
line 3
比 line 6
慢
对于具有其他大小的许多其他数组,对于 repmat
和 reshape
,可以看到比 CPU 更快的 GPU。
有人可以解释我应该怎么做才能获得预期的加速吗?
如果您看到任何令人惊讶的东西,那么您看到的只是异步执行。 a .* a
没有实际做任何事情就退出了,它只是设置了 GPU 上的计算。因此,您所计时的只是排队执行 100 个内核所花费的时间。您需要使用 gputimeit
或 wait(gpuDevice)
在您的代码中获得正确的计时。也许在 repmat
执行时达到了队列限制,因此 MATLAB 被迫等待一些乘法发生,但我不能确定。
a = rand(1000, 1000, 'gpuArray');
b = gather(a);
fprintf('Times for @times: ');
fprintf('GPU: %f secs ', gputimeit(@()a.*a));
fprintf('CPU: %f secs\n', timeit(@()b.*b));
fprintf('Times for @repmat: ');
fprintf('GPU: %f secs ', gputimeit(@()repmat(a,3,10)));
fprintf('CPU: %f secs\n', timeit(@()repmat(b,3,10)));
fprintf('Times for @reshape: ');
fprintf('GPU: %f secs ', gputimeit(@()reshape(a,10,100000)));
fprintf('CPU: %f secs\n', timeit(@()reshape(b,10,100000)));
并且输出:
Times for @times: GPU: 0.000382 secs CPU: 0.001642 secs
Times for @repmat: GPU: 0.005186 secs CPU: 0.032809 secs
Times for @reshape: GPU: 0.000053 secs CPU: 0.000002 secs
reshape
在 CPU 上可能真的更快(尽管它在噪音中下降),因为在对象上调用方法比直接检查或修改数组的属性花费更长的时间。但实际上,它是如此之快以至于对于任何真正的 GPU 应用程序都不重要。
如果您在设备上没有得到类似的数字,那么毫无疑问这与您的 GPU 质量有关。 repmat
是一种高内存带宽功能 - 也许您的游戏卡或笔记本电脑芯片对双精度阵列的性能很差?您可以在 single
尝试一下,看看情况是否有所改善。