meshgrid 和 ndgrid 的矢量化
如果您仍然有兴趣找到矢量化实现以使问题中基于meshgrid 的代码更快,让我建议使用bsxfun 的矢量化方法,它是GPU 移植版本。我坚信人们必须将vectorization with GPUs 视为加速MATLAB 代码的有希望的选择。使用meshgrid 或ndgrid 并且其输出将通过一些元素操作来操作的代码为在这些代码中使用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 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) ->')
相关函数
%// 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 的矢量化方法显示出良好的性能改进,与矢量化 CPU 代码相比 4.3x 和与原始代码相比 6x。请记住,GPU 必须克服设置所需的最小开销,因此至少需要一个合适大小的输入才能看到改进。希望人们能更多地探索vectorization with GPUs,因为它的压力还不够!