【问题标题】:matlab for loop: fastest and most efficient method to reproduce large matrixmatlab for loop:重现大型矩阵的最快和最有效的方法
【发布时间】:2012-06-11 07:19:46
【问题描述】:

我的数据是 double 值的 2096x252 矩阵。我需要一个 for 循环或执行以下操作的等效项:
每次复制矩阵时,第一个数组被删除,第二个成为第一个。当循环再次运行时,剩余的矩阵被复制,第一个数组被删除,下一个成为第一个,依此类推。 我试过使用repmat,但是在处理大型矩阵(2096x252)时它太慢而且太乏味了。

示例输入:

1 2 3 4
3 4 5 6
3 5 7 5
9 6 3 2

期望的输出:

1 2 3 4
3 4 5 6
3 5 7 5
9 6 3 2
3 4 5 6
3 5 7 5
9 6 3 2
3 5 7 5
9 6 3 2
9 6 3 2

【问题讨论】:

  • 如果我正确理解了您的问题,您的最终矩阵的大小将是2197656 x 252,我认为它的大小将超过 4.4GB。您确定这里的限制因素不是内存,而是算法的速度吗?
  • 如果内存是一个限制因素,那么您是否可以容纳代码来拼接和切块数据,这样就不会有问题了。

标签: performance matlab loops for-loop copy


【解决方案1】:

通常使用 Matlab,预先分配一个大数组比增量构建它要快得多。当您提前知道大数组的最终大小时,没有理由不遵循这个一般建议。

以下内容应该可以满足您的需求。假设你有一个数组in(nrows, ncols);那么

indices = [0 nrows:-1:1];
out = zeros(sum(indices),ncols);
for ix = 1:nrows
    out(1+sum(indices(1:ix)):sum(indices(1:ix+1)),:) = in(ix:end,:);
end

这适用于您的小型测试输入。我希望你能弄清楚发生了什么。

我不知道它是否是所有可能方法中最快的,但我希望它比增量构建大型矩阵要快得多。

【讨论】:

  • 我认为您可以通过在循环之前计算 cumsum(indices) 并在每次迭代中从预先计算的 cumsum 向量中选择下一个元素来避免每次迭代调用 sum。
  • @EitanT:是的,你确实可以这样做。
  • 我很抱歉。我仍然是matlab的新手。我没有成功执行你的代码。你能详细说明一下吗。谢谢。
  • @BernardUntalanJr。您能否更具体地说明您不成功的方式?您是否尝试过在一个小型测试矩阵(例如您的问题中的矩阵)上一次执行一行?
  • 我输入了以下代码,除了你指定的nrows=size(indices,2) ncols=size(indices,1) Matlab返回如下:未定义的函数或变量'in'。跨度>
【解决方案2】:

免责声明:
对于大型矩阵,您可能会遇到内存问题,但这不是问题。

现在,谈生意:
对于给定的矩阵A,使用for 循环的直接方法是:

[N, M] = size(A);
B = zeros(sum(1:N), M);
offset = 1;
for i = 1:N
    B(offset:offset + N - i, :) = A(i:end, :);
    offset = offset + size(A(i:end, :), 1);
end

B 是所需的输出矩阵。
但是,由于for 循环,预计此解决方案也会很慢。

编辑:预分配B,而不是动态改变大小(这种优化应该会稍微加快速度)。

【讨论】:

  • 我认为你太谦虚了,如果最终矩阵与 OP 指示的一样大,预分配 B 可能会实现巨大的加速。
  • @HighPerformanceMark,我还没有测试过大矩阵,所以我只能猜测......
  • @eitanT。谢谢它成功了!!!除了 for 循环,还有其他更有效的替代方法吗?
  • @BernardUntalanJr 目前没有任何消息,但我正在考虑。
猜你喜欢
  • 2012-07-02
  • 2013-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 2015-10-20
相关资源
最近更新 更多