matlab if语句与CUDA

时间:2012-01-29 17:04:14

标签: matlab cuda

我有以下matlab代码:

randarray = gpuArray(rand(N,1));
N = 1000;

tic
g=0;
for i=1:N

    if randarray(i)>10
        g=g+1;
    end

end
toc

secondrandarray = rand(N,1);
 g=0;

 tic 
for i=1:N

    if secondrandarray(i)>10
        g=g+1;
    end

end
toc



Elapsed time is 0.221710 seconds.
Elapsed time is 0.000012 seconds.

1)为什么GPU上的if子句这么慢?它减缓了我在优化方面的所有尝试

2)我可以做些什么来解决这个限制?

由于

4 个答案:

答案 0 :(得分:6)

无论你是在cpu还是在gpu上做这件事,这通常是件坏事。

以下是您正在进行的操作的好方法。

N = 1000;
randarray = gpuArray(100 * rand(N,1));
tic
g = nnz(randarray > 10);
toc

我没有PCT,我无法验证这是否真的有效(GPU支持的功能数量相当有限)。

但是如果你有Jacket,你肯定能够做到以下几点。

N = 1000;
randarray = gdouble(100 * rand(N, 1));
tic
g = nnz(randarray > 10);
toc

完全披露:我是开发Jacket的工程师之一。

答案 1 :(得分:1)

没有关于Matlab gpuArray实现的专家,但我怀疑第一个循环中的每个randarray(i)访问都会触发PCI-e事务以从GPU内存中检索一个值,这将导致非常大延迟惩罚。通过调用gather在单个事务中传输整个数组,然后循环遍历主机内存中的本地副本,可能会更好地为您服务。

答案 2 :(得分:1)

在现在相当老的GPU(Tesla C1060)上使用MATLAB R2011b和Parallel Computing Toolbox,这就是我所看到的:

>> g = 100*parallel.gpu.GPUArray.rand(1, 1000);
>> tic, sum(g>10); toc
Elapsed time is 0.000474 seconds.

一次对gpuArray个标量元素进行操作总是很慢,因此使用sum方法要快得多。

答案 3 :(得分:0)

我无法对先前的解决方案发表评论,因为我太新了,但延伸了Pavan的解决方案。 nxz函数(尚未)为gpuArrays实现,至少在我正在使用的Matlab版本(R2012a)上实现。

通常,矢量化Matlab代码要好得多。但是,在某些情况下,由于JIT编译,循环代码可以在Matlab中快速运行。

检查

的结果
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,因为rand永远不会给你一个高于1的值。

循环GPU版本执行可怕,因为在每次循环迭代时,都会启动内核(或者从GPU读取数据,但是TMW实现了......),这很慢。在计算基本上什么都没有的时候,很多小内存传输都是GPU上最糟糕的事情。

从上一个(最佳)GPU结果来看,答案是:除非数据已经在GPU上,否则在GPU上进行计算是没有意义的。由于操作的算术复杂性基本上不存在,因此内存传输开销不会以任何方式得到回报。如果这是更大的GPU计算的一部分,那就没关系。如果不是......更好地坚持CPU;)