我不能评论以前的解决方案,因为我太新了,但延伸了Pavan的解决方案。至少在我使用的Matlab版本(R2012a)中,nnz函数(尚未)针对gpuArrays实施。
一般来说,矢量化Matlab代码要好得多。但是,在一些情况下,循环代码可以在Matlab中快速运行,因为JIT编译。
检查从
N = 1000;
randarray_cpu = rand(N,1);
randarray_gpu = gpuArray(randarray_cpu);
threshold = 0.5;
% CPU: looped
g=0;
tic
for i=1:N
if randarray_cpu(i)>threshold
g=g+1;
end
end
toc
% CPU: vectorized
tic
g = nnz(randarray_cpu>threshold);
toc
% GPU: looped
tic
g=0;
for i=1:N
if randarray_gpu(i)>threshold
g=g+1;
end
end
toc
% GPU: vectorized
tic
g_d = sum(randarray_gpu > threshold);
g = gather(g_d); % I'm assuming that you want this in the CPU at some point
toc
哪一个是结果(我的酷睿i7 +的GeForce 560TI):
Elapsed time is 0.000014 seconds.
Elapsed time is 0.000580 seconds.
Elapsed time is 0.310218 seconds.
Elapsed time is 0.000558 seconds.
所以我们从这个案例看到的是:
循环在Matlab是不被认为是好的实践,但在你的特定情况下,它运行速度很快,因为Matlab以某种方式“内部预编译”它。我把你的门槛从10提高到了0.5,因为兰特永远不会给你一个高于1的值。
循环的GPU版本表现糟糕,因为在每次循环迭代时,启动内核(或从GPU中读取数据,但是TMW实现了......),这是很慢的。在计算基本上没有什么的时候,很多小内存传输是人们可以在GPU上做的最糟糕的事情。
从最后一个(最佳)GPU结果来看,答案是:除非数据已经在GPU上,否则在GPU上计算这些数据是没有意义的。由于您的操作的算术复杂性基本上不存在,因此内存传输开销无法以任何方式回报。如果这是更大的GPU计算的一部分,那就没问题。如果没有...更好地坚持CPU;)
所以我应该避免如果/然后像使用CUDA时的魔鬼? – 2012-01-29 18:12:36
RRs_Ghost,这将是一个好主意。当你使用if/while和其他命令时,它会将mem拷贝回主机。在for循环中一堆小(1个元素)mem副本是一个坏主意。 – 2012-01-29 18:23:51
@Pavan:我不相信PCT中的当前gpuArray实现支持nnz。 – talonmies 2012-01-29 19:08:59