【问题标题】:How to speed up a for while loop in Matlab如何在 Matlab 中加速 for while 循环
【发布时间】:2021-11-15 15:56:36
【问题描述】:

我在Matlab中定义了两个相同大小的向量tcoverage,我需要定义第三个向量n_steps。 特别是我需要加快以下循环:

t = 1:100000;
coverage = double(rand(size(t)) > 0.9);

for j=1:(length(t)-1)
    n_steps(j)=0;

    while coverage(j+n_steps(j)+1)==0  && j+n_steps(j)+1<length(t)
        n_steps(j)=n_steps(j)+1;
    end
    
end

t是一个时间向量,每个时间步的coverage可以为1或0。 对于每个瞬间t(j),我必须找到时间步数n_steps(j) 在第一个1 出现在向量coverage(j+1:length(coverage)) 之前等待,

【问题讨论】:

  • 为什么要矢量化该循环?你喜欢难以阅读的代码吗? MATLAB 循环已经很久没有变慢了。您可以改进您的代码逻辑,首先提取所有coverage 为非零的索引(find),然后为每个j 找到大于j 的第一个值。
  • 你好克里斯·伦戈。我需要矢量化只是因为它需要很长时间才能运行。我想矢量化以更快地获得它。我正在使用 Matlab 2013,您认为这可能是问题所在吗?
  • 一般来说,您可以使用values = coverage(j+index+1)==0 &amp;&amp; j+index+1&lt;length(t);while coverage(j+index+1)==0 &amp;&amp; j+index+1&lt;length(t); 转换为位掩码。我不知道你在做什么,因为我没有 tindexcoverage
  • 你应该问“我怎样才能加快这个循环?”矢量化有时会使代码更快一些,有时会使代码变慢很多。在 2006 年左右引入 JIT 之前,矢量化非常重要,但现在不再如此。为矢量化而矢量化使您看起来像是在遵循 15 年的习惯。当你写coverage(j+index+1)时,你的意思是coverage(j+index(j)+1)吗?您是否预先分配了index?如果您提供minimal reproducible example,人们会更容易帮助您。
  • 谢谢大家的回复。我试图为这个问题提供更多细节。希望你现在能更好地帮助我。

标签: matlab vectorization


【解决方案1】:

您的代码(以及我添加到其中的示例数据)在 MATLAB Online 上运行时间为 0.0163 秒。只需添加

n_steps = zeros(1,length(t)-1);

在循环之前将执行时间减少到 0.0057 秒。预分配非常很重要!

接下来,我可以稍微更改您的代码,这样您就不需要一遍又一遍地搜索同一个数组:

n_steps = zeros(1,length(t)-1);
cov = [find(coverage), length(t)];
k = 1;
for j=1:(length(t)-1)
    if cov(k) <= j
        k = k+1;
    end
    n_steps(j) = cov(k) - j - 1;
end

此代码在 0.0015 秒内运行。它依赖于创建一个较小的数组cov,其中包含coverage 中非零元素的索引。 cov(k) 是非零元素的 coverage 的索引。当我们向前移动j 时,有时我们也需要向前移动索引k,这样cov(k)j 之后。

也许可以进一步矢量化外循环,但我怀疑它会使代码更快。


这是我为计时和测试正确性编写的脚本:

t = 1:100000;
coverage = double(rand(size(t)) > 0.9);

timeit(@() method1(t, coverage))
timeit(@() method2(t, coverage))
timeit(@() method3(t, coverage))

a = method1(t, coverage);
b = method3(t, coverage);
assert(isequal(a,b))

function n_steps = method1(t, coverage)
for j=1:(length(t)-1)
    n_steps(j)=0;
    while coverage(j+n_steps(j)+1)==0  && j+n_steps(j)+1<length(t)
        n_steps(j)=n_steps(j)+1;
    end
end
end

function n_steps = method2(t, coverage)
n_steps = zeros(1,length(t)-1);
for j=1:(length(t)-1)
    while coverage(j+n_steps(j)+1)==0  && j+n_steps(j)+1<length(t)
        n_steps(j) = n_steps(j)+1;
    end
end
end

function n_steps = method3(t, coverage)
n_steps = zeros(1,length(t)-1);
cov = [find(coverage), length(t)];
k = 1;
for j=1:(length(t)-1)
    if cov(k) <= j
        k = k+1;
    end
    n_steps(j) = cov(k) - j - 1;
end
end

【讨论】:

  • 你好@CrisLuengo。非常感谢您如此详细的回复。在我今天运行我的原始代码的效果中,它通常要快得多。无论如何,您的代码甚至更快,现在我将使用它。再次非常感谢您
猜你喜欢
  • 2016-01-31
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-08
  • 1970-01-01
  • 2014-05-19
相关资源
最近更新 更多