我有一个更新数组的 Matlab 模拟:
Array=zeros(1,1000)
如下:
for j=1:100000
Array=Array+rand(1,1000)
end
我的问题如下: 此循环是线性的,因此不能针对阵列中的每个插槽进行并列化,但不同的插槽是独立更新的。因此,Matlab 自然会使用 CPU 的所有内核在 parralell 中执行这样的数组操作。
我希望在我的 NVIDIA GPU 上执行相同的计算,以加快速度(利用那里的更多内核)。
问题是:天真地做
tic
Array=gpuArray(zeros(1,1000));
for j=1:100000
Array=Array+gpuArray(rand(1,1000));
end
toc
结果计算时间延长了8倍!
一个。我做错了什么?
更新: b.也许有人可以提供另一个简单的例子,GPU 计算对它有益?我的目的是了解如何在 Matlab 中利用它来进行非常"繁重"的随机模拟(对大数组和矩阵的多个线性运算)。
什么都没有。
这就是 GPU 计算的工作方式。不幸的是,这不是魔法。CPU-GPU 通信很慢,非常慢。每次迭代,您都会在CPU上创建一个数组并将其发送到GPU,这是缓慢的部分。我敢肯定,CPU"+"操作中快得离谱的速度在 GPU 中甚至更快,但将信息发送到 GPU 所需的时间完全掩盖了这种改进。
您的代码几乎没有改进的余地。
它可能无助于整体速度(正如@Ander在他的回答中提到的),但你可以做的一个小改进是直接在GPU上构建随机数,如下所示:
rand(1, 10000, 'gpuArray')
通常,GPU 上的随机数生成比 CPU 上的要快得多。
您可以使用gpuArray
版本的arrayfun
更进一步,它将主体 JIT 编译为本机 GPU 代码。在我的GPU(Tesla K20c)上,这使得GPU版本比CPU版本快10倍。以下是完整脚本:
%% CPU version
tic
Array=zeros(1,1000);
for j=1:100000
Array=Array+rand(1,1000);
end
cpuTime = toc
%% GPU version
dev = gpuDevice();
tic
Array = zeros(1, 1000, 'gpuArray');
Array = arrayfun(@iFcn, Array);
wait(dev);
gpuTime = toc
%% Arrayfun body
function x = iFcn(x)
for j = 1:100000
x = x + rand;
end
end