6

Matlab 中的矢量化代码比 for 循环运行得快得多(请参阅单台机器上的 Octave 中的并行计算——Octave中具体结果的包和示例)

话虽如此,有没有办法对接下来在 Matlab 或 Octave 中显示的代码进行矢量化?

x = -2:0.01:2;
y = -2:0.01:2;
[xx,yy] = meshgrid(x,y);
z = sin(xx.^2-yy.^2);
4

3 回答 3

7

正如@Jonas 所指出的,MATLAB 中有几个可用的选项,哪个效果最好取决于几个因素,例如:

  • 你的问题有多大
  • 你有多少台机器可用
  • 你有GPU吗
  • MATLAB 是否已经对操作进行了多线程处理

现在,MATLAB 中的许多元素操作都是多线程的 - 在这种情况下,使用 PARFOR 通常没有什么意义(除非您有多台机器和 MATLAB 分布式计算服务器许可证)。

真正需要多台机器内存的大问题可以从分布式阵列中受益。

如果您的问题具有适合 GPU 计算的大小和类型,则使用 GPU 可以超越单台机器的多线程性能。矢量化代码往往最适合通过 GPU 进行并行化。例如,您可以gpuArray像这样使用 Parallel Computing Toolbox 中的 s 编写代码,并让所有内容都在 GPU 上运行。

x = parallel.gpu.GPUArray.colon(-2,0.01,2);
y = x;
[xx,yy] = meshgrid(x,y); % xx and yy are on the GPU
z = arrayfun( @(u, v) sin(u.*u-v.*v), xx, yy );

我将那里的最后一行转换为调用,因为使用sarrayfun时效率更高。gpuArray

于 2012-05-11T07:08:31.360 回答
6

和的矢量meshgridndgrid

如果您仍然有兴趣找到一个矢量化实现以使meshgrid问题中的基于代码更快,让我建议一个矢量化方法,bsxfun它是 GPU 移植版本。我坚信人们必须将其vectorization with GPUs视为加快MATLAB代码速度的有希望的选择。使用meshgridorndgrid并且其输出将通过一些元素操作进行操作bsxfun的代码为这些代码提供了完美的基础。除此之外,将 GPU 与 结合使用bsxfun,使其能够独立处理具有成百上千个可用 CUDA 内核的元素,使其非常适合 GPU 实现。

对于您的具体问题,输入是 -

x = -2:0.01:2;
y = -2:0.01:2;

接下来,你有 -

[xx,yy] = meshgrid(x,y);
z = sin(xx.^2-yy.^2);

随着bsxfun,这变成了一个单行 -

z = sin(bsxfun(@minus,x.^2,y.^2.'));

基准测试

GPU 基准测试技巧取自Measure and Improvement GPU Performance

%// Warm up GPU call with insignificant small scalar inputs
temp1 = sin_sqdiff_vect2(0,0);

N_arr = [50 100 200 500 1000 2000 3000]; %// array elements for N (datasize)
timeall = zeros(3,numel(N_arr));

for k = 1:numel(N_arr)
    N = N_arr(k);
    x = linspace(-20,20,N);
    y = linspace(-20,20,N);

    f = @() sin_sqdiff_org(x,y);%// Original CPU code
    timeall(1,k) = timeit(f);
    clear f

    f = @() sin_sqdiff_vect1(x,y);%// Vectorized CPU code
    timeall(2,k) = timeit(f);
    clear f

    f = @() sin_sqdiff_vect2(x,y);%// Vectorized GPU(GTX 750Ti) code
    timeall(3,k) = gputimeit(f);
    clear f
end

%// Display benchmark results
figure,hold on, grid on
plot(N_arr,timeall(1,:),'-b.')
plot(N_arr,timeall(2,:),'-ro')
plot(N_arr,timeall(3,:),'-kx')
legend('Original CPU','Vectorized CPU','Vectorized GPU (GTX 750 Ti)')
xlabel('Datasize (N) ->'),ylabel('Time(sec) ->')

相关功能

%// Original code
function z = sin_sqdiff_org(x,y)
[xx,yy] = meshgrid(x,y);
z = sin(xx.^2-yy.^2);
return;

%// Vectorized CPU code
function z = sin_sqdiff_vect1(x,y)
z = sin(bsxfun(@minus,x.^2,y.^2.')); %//'
return;

%// Vectorized GPU code
function z = sin_sqdiff_vect2(x,y)
gx = gpuArray(x);
gy = gpuArray(y);
gz = sin(bsxfun(@minus,gx.^2,gy.^2.')); %//'
z =  gather(gz);
return;

结果

在此处输入图像描述

结论

结果表明,使用 GPU 的矢量化方法显示出良好的性能改进,这4.3x与矢量化 CPU 代码和6x原始代码相比。请记住,GPU 必须克服设置所需的最小开销,因此至少需要一个合适大小的输入才能看到改进。希望人们会探索更多vectorization with GPUs,因为它的压力不够大!

于 2014-08-06T13:58:24.093 回答
5

在 Matlab 中,将内置向量化函数用于多线程的唯一方法是等待 MathWorks实现它们

或者,您可以将矢量化计算编写为一个循环,并使用parfor.

最后,许多函数都支持 GPU,因此通过访问并行处理工具箱,您可以并行化这些操作,包括减法和逐元素运算。

于 2012-05-11T01:16:44.927 回答