正如commentedSteve Eddins一样,对于小数组大小,implicit expansion(在Matlab R2016b中引入)比 bsxfun 更快,而对于大数组则具有类似的速度:



此外,展开所沿的维度可能会产生影响:



(感谢@Poelie@rayryeng让我know about这个!)

自然会产生两个问题:

  • 隐式扩展比bsxfun快多少?
  • 差异对于什么数组大小或形状有意义?
  • 最佳答案

    为了测量速度差异,已进行了一些测试。测试考虑两种不同的操作:

  • 添加
  • 电源

  • 分别对要操作的数组的四种不同形状进行操作:
  • 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 用于可靠的计时。
    基准代码在此答案的末尾给出。它已在具有12 GB RAM的Windows 10 Matlab R2016b上运行。
    结果
    下图显示了结果。水平轴是输出数组的元素数,它比N更好地衡量大小。
    arrays - 隐式扩展比bsxfun快多少?-LMLPHP
    arrays - 隐式扩展比bsxfun快多少?-LMLPHP
    还已经使用逻辑运算(而不是算术运算)进行了测试。为了简洁起见,此处未显示结果,但显示了类似的趋势。
    结论
    根据图形:
  • 结果证实,小数组的隐式扩展更快,并且与大数组的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')
    

    关于arrays - 隐式扩展比bsxfun快多少?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42559922/

    10-11 22:36