【问题标题】:Vectorize a for loop to fill row向量化 for 循环以填充行
【发布时间】:2018-09-14 20:24:23
【问题描述】:

我尝试对以下内容进行矢量化:

for i = 2:n
    mat = NaN(m,i);
    for j = 1:m
        mat(j,:) = getVal(i);
    end
    num(i) = max(mat(:));
end

进入

for i = 2:n
    mat = NaN(m,i);
    j = 1:m;
    mat(j,:) = getVal(i);
    num(i) = max(mat(:));
end

但是,MATLAB 给我一个错误:“下标赋值维度不匹配”我不确定我的代码哪里出错了?

另外,是否可以矢量化整个嵌套的 for 循环,而不仅仅是内部循环?

谢谢!

编辑:抱歉,getVal() 函数返回一个大小为“i”的随机向量。这用于在提供的代码中填充矩阵的行,因此这篇文章的问题标题为“Vectorize a for loop to fill row”。抱歉,如果不清楚。

样本数据: 对于 i = 2,输出将如下所示: Matrix Output 1 矩阵的行在内循环中一次填充一个。 对于 i = 3,它与上面的相同,改为 3 列: Matrix Output 2

希望这很清楚吗?

编辑 2: 我刚刚按照 Cris Luengo 的解决方案的建议尝试使用 repmat。这是我的输出:Matrix Output with repmat。我需要每次运行函数 getVal,而不是简单地运行一次并将其内容复制到行中。

编辑 3: 好的,这是我的函数 getVal(i):

function [A] = getVal(m)
    X = normrnd(0,1,[m,m]);
    A = triu(X) + triu(X)';
    A = A - diag(diag(A))/2;
    A = eig(A)';
end

【问题讨论】:

  • 1. 请提供一些示例数据来运行您的循环。 2. getVal 是矩阵吗?它是一个功能吗?它是什么?请提供minimal reproducible example3.请解释一下你的循环是做什么的。
  • 抱歉!刚刚更新了! @SardarUsama
  • @CrisLuengo 是的,你是对的。我似乎误解了矢量化的概念,并天真地认为它会加快进程。如果有帮助,我上传了该功能。
  • @CrisLuengo 抱歉,我已经解决了。它运行良好,只是错过了最后一行。
  • @StaticCrazee: eig 使得矢量化变得困难。 this FileExchange submissioneig 计算向量化,但仅适用于 2x2 或 3x3 矩阵。我不知道如何矢量化您的代码。但是你的问题现在已经完成了,所以我要推翻我的反对意见。

标签: matlab optimization vectorization nested-loops


【解决方案1】:

从您的示例中, getVal(i) 不会不断返回相同的输出来重复调用它。由于我没有您的代码,因此我使用以下方法模拟了该行为:

function out = getVal(i)
   out = rand(1, i);
end

现在,如果您无法触摸 getVal 但希望将所有内容矢量化,我会使用 arrayfun (https://www.mathworks.com/help/matlab/ref/arrayfun.html)

mat = cell2mat(arrayfun(@getVal, repmat(i, m, 1), 'UniformOutput', false)); % UniformOutput is needed because output isn't a scalar. Cell2mat is used to convert to the same matrix as previously.

您的代码的其余部分是相同的。请注意,一切都像以前一样工作,只是没有循环。

但是你仍然有外循环。另一个 arrayfun 处理:

num = arrayfun(@(i, m) max(max(cell2mat(arrayfun(@getVal, repmat(i, m, 1), 'UniformOutput', false)))), 1:n, repmat(m, 1, n));

请注意,这不会计算 mat,但我认为它并不是真正需要的,因为它会不断为每个 i 重写。

但是......它并不快。我用 n=1000, m=1000 计时,你的 2 循环代码给了我 7.3 秒,第一个矢量化方法在 10.8 秒内完成,最后一个在 10.7 秒内完成,2 循环方法再次在 7.1 结束这次是。

真正加快代码速度的明显步骤是矢量化 getVal - 只要我不知道它到底做了什么,我就无法帮助您。但是如果这种上兰特方法在大约 5 秒内完成,如果它在一个步骤中返回整个垫子。

【讨论】:

  • 正是我想要的!非常感谢你,Zizy!
  • arrayfun 在内部使用循环,在这种情况下使用它是没有意义的。您使用函数句柄添加了一个间接级别,因此会产生额外的成本。这段代码比 OP 更难阅读,因此更糟糕,即使时间相同。在单行上编写 3 语句程序不是向量化的。
  • @CrisLuengo 是的。有没有办法对其进行矢量化?
  • @StaticCrazee:如果您的代码太慢,请告诉我们getVal(如果可以的话)。那就是需要向量化的函数。你的双循环很好,你不能加快速度。费用是拨打getVal
猜你喜欢
  • 2015-01-02
  • 1970-01-01
  • 2016-11-01
  • 2014-11-22
  • 2016-03-09
  • 2019-05-17
  • 1970-01-01
相关资源
最近更新 更多