Matlab(或Octave)中的meshgrid矢量化

db1*_*234 5 parallel-processing matlab vectorization octave

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);
Run Code Online (Sandbox Code Playgroud)

Edr*_*ric 6

正如@Jonas所指出的,MATLAB中有一些选项可供选择,其效果最好取决于以下几个因素:

  • 你的问题有多大?
  • 你有多少台机器
  • 你有GPU吗?
  • MATLAB是否已经多线程操作

现在,许多元素操作在MATLAB中是多线程的 - 在这种情况下,使用PARFOR通常没什么意义(除非你有多台机器和MATLAB Distributed Computing Server许可证可用).

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

如果您的问题具有适合GPU计算的大小和类型,则使用GPU可以击败单个机器的多线程性能.矢量化代码往往最适合通过GPU进行并行化.例如,您可以使用gpuArrayParallel 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 );
Run Code Online (Sandbox Code Playgroud)

我将最后一行转换为arrayfun调用,因为使用gpuArrays 时效率更高.


Jon*_*nas 5

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

或者,您可以将矢量化计算编写为循环,并使用并行运行它们parfor.

最后,许多功能都支持GPU,因此通过访问并行处理工具箱,您可以并行化这些操作,包括减法和元素功率.


Div*_*kar 5

矢量化meshgridndgrid

如果您仍然有兴趣找到一个矢量化实现来meshgrid更快地使代码中的代码更快,那么让我建议使用带有bsxfunGPU移植版本的矢量化方法.我坚信人们必须将其vectorization with GPUs作为加速MATLAB代码的有前途的选择.使用meshgrid或者ndgrid其输出将通过一些元素操作来操作的bsxfun代码设置了完美的基础以用于那些代码.除此之外bsxfun,GPU的使用使得它可以独立地使用成百上千个CUDA内核,这使得它非常适合GPU实现.

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

x = -2:0.01:2;
y = -2:0.01:2;
Run Code Online (Sandbox Code Playgroud)

接下来,你有 -

[xx,yy] = meshgrid(x,y);
z = sin(xx.^2-yy.^2);
Run Code Online (Sandbox Code Playgroud)

随着bsxfun,这成为一个单线 -

z = sin(bsxfun(@minus,x.^2,y.^2.'));
Run Code Online (Sandbox Code Playgroud)

标杆

GPU基准测试技巧来自Measure and Improve 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) ->')
Run Code Online (Sandbox Code Playgroud)

相关功能

%// 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;
Run Code Online (Sandbox Code Playgroud)

结果

在此输入图像描述

结论

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