Lui*_*ndo 23 arrays performance matlab bsxfun
正如Steve Eddins 评论的那样,隐式扩展(在Matlab R2016b中引入)比小数组大小更快,并且对于大型数组具有相似的速度:bsxfun
在R2016b中,在大多数情况下,隐式扩展的工作速度比bsxfun快或快.隐式扩展的最佳性能增益是小矩阵和数组大小.对于大矩阵大小,隐式扩展往往与大致相同
bsxfun.
此外,扩展所发生的维度可能会产生影响:
当第一维中存在扩展时,运算符可能不会那么快
bsxfun.
(感谢@Poelie和@rayryeng让我知道 关于这个!)
自然会出现两个问题:
bsxfun?Lui*_*ndo 19
为了测量速度的差异,已经进行了一些测试.测试考虑两种不同的操作:
以及要操作的四种不同形状的阵列:
N×N数组的N×1数组N×N×N×N数组的N×1×N数组N×N数组的1×N数组N×N×N×N数组的1×N×N数组对于操作和数组形状的八种组合中的每一种,使用隐式扩展和使用相同的操作bsxfun.使用了几个值N,以涵盖从小型到大型阵列的范围.timeit用于可靠的计时.
基准代码在本答案的最后给出.它已在Matlab R2016b,Windows 10上运行,具有12 GB RAM.
下图显示了结果.水平轴是输出数组的元素数,这是一个更好的尺寸度量N.
测试也是通过逻辑运算(而不是算术运算)完成的.为简洁起见,此处未显示结果,但显示了类似的趋势.
根据图表:
bsxfun大型阵列.timeit对于小尺寸而言,这是不准确的,因为代码太快(实际上,它会针对如此小的尺寸发出警告).1e5.该值可能与系统有关.由于速度提升仅在阵列较小时才显着,这种情况下任何一种方法都非常快,使用隐式扩展或bsxfun似乎主要是品味,可读性或向后兼容性的问题.
clear
% NxN, Nx1, addition / power
N1 = 2.^(4:1:12);
t1_bsxfun_add = NaN(size(N1));
t1_implicit_add = NaN(size(N1));
t1_bsxfun_pow = NaN(size(N1));
t1_implicit_pow = NaN(size(N1));
for k = 1:numel(N1)
N = N1(k);
x = randn(N,N);
y = randn(N,1);
% y = randn(1,N); % use this line or the preceding one
t1_bsxfun_add(k) = timeit(@() bsxfun(@plus, x, y));
t1_implicit_add(k) = timeit(@() x+y);
t1_bsxfun_pow(k) = timeit(@() bsxfun(@power, x, y));
t1_implicit_pow(k) = timeit(@() x.^y);
end
% NxNxNxN, Nx1xN, addition / power
N2 = round(sqrt(N1));
t2_bsxfun_add = NaN(size(N2));
t2_implicit_add = NaN(size(N2));
t2_bsxfun_pow = NaN(size(N2));
t2_implicit_pow = NaN(size(N2));
for k = 1:numel(N1)
N = N2(k);
x = randn(N,N,N,N);
y = randn(N,1,N);
% y = randn(1,N,N); % use this line or the preceding one
t2_bsxfun_add(k) = timeit(@() bsxfun(@plus, x, y));
t2_implicit_add(k) = timeit(@() x+y);
t2_bsxfun_pow(k) = timeit(@() bsxfun(@power, x, y));
t2_implicit_pow(k) = timeit(@() x.^y);
end
% Plots
figure
colors = get(gca,'ColorOrder');
subplot(121)
title('N\times{}N, N\times{}1')
% title('N\times{}N, 1\times{}N') % this or the preceding
set(gca,'XScale', 'log', 'YScale', 'log')
hold on
grid on
loglog(N1.^2, t1_bsxfun_add, 's-', 'color', colors(1,:))
loglog(N1.^2, t1_implicit_add, 's-', 'color', colors(2,:))
loglog(N1.^2, t1_bsxfun_pow, '^-', 'color', colors(1,:))
loglog(N1.^2, t1_implicit_pow, '^-', 'color', colors(2,:))
legend('Addition, bsxfun', 'Addition, implicit', 'Power, bsxfun', 'Power, implicit')
subplot(122)
title('N\times{}N\times{}N{}\times{}N, N\times{}1\times{}N')
% title('N\times{}N\times{}N{}\times{}N, 1\times{}N\times{}N') % this or the preceding
set(gca,'XScale', 'log', 'YScale', 'log')
hold on
grid on
loglog(N2.^4, t2_bsxfun_add, 's-', 'color', colors(1,:))
loglog(N2.^4, t2_implicit_add, 's-', 'color', colors(2,:))
loglog(N2.^4, t2_bsxfun_pow, '^-', 'color', colors(1,:))
loglog(N2.^4, t2_implicit_pow, '^-', 'color', colors(2,:))
legend('Addition, bsxfun', 'Addition, implicit', 'Power, bsxfun', 'Power, implicit')
Run Code Online (Sandbox Code Playgroud)