【问题标题】:Selecting a vector from a matrix without using `sub2ind`从矩阵中选择一个向量而不使用 `sub2ind`
【发布时间】:2012-02-10 19:42:41
【问题描述】:

我有一个 5 x 5 矩阵 M 和两个向量

x=[1:5]
y=[1 4 3 5 2]

我想提取 M 中带有下标 (x,y) 的元素,即 (1,1),(2,4),(3,3),(4,5),(5,2) .当然,我可以做类似的事情

M(sub2ind([5,5],x,y))

但是有一些与转换为索引相关的开销。有没有其他方法可以做到这一点?

【问题讨论】:

  • 简单地做M(x,y)不行吗?
  • diag(M(x,y)) 应该可以,但我不确定它的效率如何

标签: matlab


【解决方案1】:

MATLAB 使用 Column Major 格式,为什么不利用它呢? M 为 5x5 所以, 第一列是 M(1)、M(2)、M(3)、M(4)、M(5)。 所以,概括一下:

M(x,y) = M((x+(y-1)*5)

【讨论】:

  • 我认为 sub2ind 可能会快一点。
  • 不。我反复测试它。 >> a = rand(5000,5000); >> x = 1:5000; >> y = randperm(5000); >> tic;p2=a(x+(y-1)*5000);toc; Elapsed time is 0.000732 seconds. >> tic;p=a(sub2ind([5000,5000],x,y));toc; Elapsed time is 0.001371 seconds.
  • sub2ind 基本相同,只是与错误检查、泛化等相关的开销。看看sub2ind.m
  • 我知道,但既然知道自己在做什么,为什么还要使用不必要的开销呢?
【解决方案2】:

您可以将匿名函数句柄与 arrayfun 方法结合使用:

% declare an anonymous function which operates on M with args x and y
fun = @(x,y)(M(x,y)); 
% Ask arrayfun to execute "fun" for each pair of x and y.
arrayfun(fun, x, y); 

【讨论】:

  • +1 - 创意。但是应该有一些像最初的方法一样的开销,甚至更多。
【解决方案3】:

没有答案。但因为我感兴趣,所以我自己进行测试。

M = magic(5)
x=[1:5];
y=[1 4 3 5 2];

%%
tic
for i=1:10000
    out = M(sub2ind([5,5],x,y));
end
toc % Elapsed time is 0.413526 seconds.
out
%%
tic
for i=1:10000
    out = M(x+(y-1)*5);
end
toc % Elapsed time is 0.024004 seconds.
out
%%
fun = @(x,y)(M(x,y)); 
tic
for i=1:10000
    out = arrayfun(fun,x,y);
end
toc % Elapsed time is 0.449727 seconds.
out
%%
fun = @(x,y)(M(x,y)); 
tic
for i=1:10000
    out = nan(1,5);
    for j=1:5
        out(j) = M(x(j),y(j));
    end
end
toc % Elapsed time is  0.045242 seconds.
out

(抱歉在第一个程序中出现了愚蠢的复制粘贴错误)

我没有将 for 循环排在第二位。

我在 2011b - 所以似乎进步了很多。

【讨论】:

  • 那些时候.. BARF
【解决方案4】:

我认为您的 sub2ind 方法是最快的。

如果您考虑可读性 - 可以在 for 循环中阅读。

【讨论】:

  • 你的意思是代码可读性吗?我认为 for 循环在 matlab 数组操作中是一个很大的禁忌,因为它们的开销很大?
  • 他们的表现很差。但是对于调试,它们比大多数矢量化结构更容易阅读。
  • 也 for 是许多语言中使用的标准结构。遗憾的是他们仍然没有在 matlab 中修复这个问题 - 但每个版本都会变得更好。
  • 在 MATLAB 中的 for 循环具有“巨大的开销”是一个神话,这在某个时候是真的,比如 8 年前。随着 JIT 代码和其他优化的引入,矢量化不再像以前那么重要,在某些情况下甚至可能是有害的。
猜你喜欢
  • 2019-09-04
  • 2017-02-16
  • 1970-01-01
  • 2021-09-12
  • 1970-01-01
  • 2011-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多