【问题标题】:Speeding up for loop since I run out of memory when I vectorise it加速循环,因为当我矢量化它时内存不足
【发布时间】:2013-12-10 12:58:12
【问题描述】:

我能够在矢量化这个 for 循环方面获得帮助,但是如果我尝试在 array1 / xfreq_orig 有 500,000 行或 t_rebuilt 有 500,000 行时运行它,我会用完 16gig 的 ram。

array1=[xfreq_orig,yamp_orig,yamp_inv,phase_orig] %frequency, amplitudes, phases to use
t_rebuilt=linspace(0,2*pi,44100)


aa_sig_rebuilt_L=zeros(1,length(t_rebuilt));
aa_sig_combined_L=zeros(1,length(t_rebuilt));
sig_full_L=zeros(1,length(t_rebuilt));

for kk=1:1:numel(xfreq_orig);

    aa_sig_rebuilt_L = array1(kk, 2)*cos ((array1(kk,1))*t_rebuilt+(array1(kk, 4))); 
    aa_sig_combined_L = aa_sig_combined_L + aa_sig_rebuilt_L;

end

sig_full_L=(aa_sig_combined_L/max(abs(aa_sig_combined_L))*.8);

这是矢量化版本,但是当 array1 / xfreq_orig 行像 500,000 一样大或者如果 t_rebuilt 是像 t_rebuilt= 这样的大数组时,我的内存不足linspace(0,2*pi,544100)

a = array1;
t = t_rebuilt;

aa_sig_rebuilt_L  = bsxfun(@times, a(:,2) , ...
                     cos( bsxfun(@plus, bsxfun(@times, a(:,1), t), a(:,4)) ));

aa_sig_combined_L = sum(aa_sig_rebuilt_L);

以下是 Chris Taylor 回答的原因解释。 “请记住,这将使用比版本循环更多的内存(它将使用 numel(xfreq_orig) 倍的内存,因为它在求和之前计算 aa_sig_rebuilt_L 的每一行,而循环计算每一行,将其添加到总和然后丢弃它)。”

vectorizing a matlab / octave FOR loop

有没有人对如何加快这个 for 循环有任何建议,因为如果我将它矢量化,我会耗尽内存?是否有另一种方法对其进行矢量化,以便在 array1 / xfreq_orig 或 t_rebuilt

使用大量行时不会耗尽内存

【问题讨论】:

    标签: matlab for-loop octave vectorization


    【解决方案1】:

    是的,在这种情况下bsxfun(三次!)可能不是一个好主意。有时,人们对 Matlab 中的循环的偏执过度。它们非常好,如果在适当的情况下使用,在许多情况下可以比其他选项更快(并且具有可读性强的好处)。像您的系统这样的更新方程和递归关系正是可以通过for 循环更好地实现的系统类型。如果您为较小的输入计时循环和bsxfun 代码,您会发现它们非常具有可比性。

    您正在代码中进行看起来很多不必要的分配。例如,aa_sig_rebuilt_Lsig_full_L 不需要预先分配。它们在初始化时会自动分配。您还从较小的数组构建了一个大数组array1,并在for 循环的每次迭代中执行二维索引。这些将清理您的代码,并且可能会稍微加快速度,但是实际上,您将摆脱临时变量aa_sig_rebuilt_L 并将所有内容放在一条线上,从而获得最大的速度提升。这不应该与 JIT 编译一起使用,但有时可以。这是我的版本:

    t_rebuilt = linspace(0,2*pi,544100);
    aa_sig_combined_L1 = zeros(1,length(t_rebuilt));
    for i=1:length(xfreq_orig);
        aa_sig_combined_L1 = aa_sig_combined_L1 + ...
            yamp_orig(i)*cos(xfreq_orig(i)*t_rebuilt+phase_orig(i));
    end
    

    在我的机器上运行仍然需要一段时间,但你不应该用完内存,除非你的代码的其他部分已经用完了它(检查whos)。如果您确实内存不足,您可以尝试使用clear (in Octave) 显式清除未使用的大型变量。除此之外,您可以探索使用mex 编写代码或使用codgen 自动将您的函数输出为可从Matlab 调用的C 代码。八度:Dynamically Linked Functions – Oct-Files and Mex-Files.

    【讨论】:

      【解决方案2】:

      一方面,您想使用 Matlab 向量化,意思是使用所有数据。另一方面,你不能这样做,因为你没有足够的内存。即使你有足够的内存,分配大量 RAM 也会导致计算速度变慢。

      其中一种解决方案是将数据拆分为多个部分,从磁盘加载相关部分,然后对其进行矢量化计算。您可以对这个参数进行一些尝试,看看什么会产生最佳性能。

      【讨论】:

        猜你喜欢
        • 2015-05-17
        • 2011-11-30
        • 2018-11-13
        • 2013-05-25
        • 2013-12-12
        • 2021-04-06
        • 1970-01-01
        • 1970-01-01
        • 2012-09-24
        相关资源
        最近更新 更多