Using vector instead of Loop
我有一个巨大的矩阵。我刚刚给出了一个大小为 (1*1000000).
的矩阵示例
我正在使用简单的 Loop(我不喜欢使用 Loop)来查找 k。
k= k(ii)=(abs(a(ii+1)-2*a(ii)+a(ii-1)))/(a(ii+1)+2*a(ii)+a(ii-1))
但是,这对于小矩阵来说很好。如果我有大量数据需要很长时间。有什么方法可以使用向量而不是 Loop 来查找 k?
1 2 3 4 5 6 7
| clear;
clc;
a= rand(1, 1000000);
for ii= 2: size(a, 2)- 1
k (ii )= (abs(a (ii+ 1)- 2*a (ii )+a (ii- 1)))/ (a (ii+ 1)+ 2*a (ii )+a (ii- 1));
end |
- 如果你预先分配 k 你的循环会快很多。 mathworks.com/help/matlab/matlab_prog/preallocating-arrays.h??tml
-
在 MATLAB 中使用循环没有任何问题。他们曾经很慢,但现在不再如此。
-
@Cris Luengo。谢谢
如果你想对它进行矢量化,你需要知道在每次迭代中你将使用 a 的哪些索引。例如,术语 a(ii+1) 与 ii 从 2 迭代到 999999 意味着您正在使用从索引 3 到 last 的 a 元素,并且类似地找出其他术语。然后只需按元素进行除法 ./。 0 是在开始时手动附加的,因为在您的代码中,您没有在第一个索引处显式存储任何内容,并且当您跳过索引时自动存储的内容为零。
1
| k = [0 abs(a (3: end)- 2*a (2:end- 1)+a (1:end- 2)) ./ (a (3: end)+ 2*a (2:end- 1)+a (1:end- 2))]; |
使用 R2017a 和 a=rand(1,1e8); 在我的系统上使用 timeit 计时的性能:
1 2 3
| Orig_Post = 14.3219
Orig_Post_with_Preallocation = 1.7764
Vectorised = 5.3292 |
因此可以看出循环在较新的版本中得到了显着改进。事实证明,具有为 k 正确预分配内存的循环的解决方案比向量化的解决方案快得多。您遇到的性能下降是由于没有预分配(正如 Cris Luengo 已经建议的那样)。要预分配,请编写 k = zeros(1, size(a,2)-1);
在循环之前。
- 我没有你那么有耐心,所以我尝试使用 1e6 来确定数组大小(R2017a)。我看到 0.055 没有预分配,0.0087 有,0.018 有矢量化代码。与您的结果相似。我期望矢量化代码的成本相似或略好于循环,而不是更差。这可能是我迄今为止看到的第三个例子,其中循环比相应的矢量化代码更快。我认为在这种情况下,这是因为矢量化代码需要更多的数据副本和中间结果。我敢肯定,这都是关于内存使用和缓存未命中的。
-
此外,分离索引以避免这样做两次:a3 = a(3:end); a2 = a(2:end-1); a1 = a(1:end-2); k = [0 abs(a3-2*a2+a1) ./ (a3+2*a2+a1)];。这给了我 0.011,更接近循环时间。我尝试做 a2 = 2*...,不相乘两次,也尝试做 a0=a3+a1,不做两次加法,但两次时间都增加了。莫名其妙!