Aur*_*dal 6 optimization matlab loops for-loop octave
我试图通过摆脱一些 for 循环来优化我的代码的运行时间。但是,我有一个在每次迭代中递增的变量,其中有时会重复索引。我在这里提供一个最小的例子:
a = [1 4 2 2 1 3 4 2 3 1]
b = [0.5 0.2 0.3 0.4 0.1 0.05 0.7 0.3 0.55 0.8]
c = [3 5 7 9]
for i = 1:10
c(a(i)) = c(a(i)) + b(i)
end
Run Code Online (Sandbox Code Playgroud)
理想情况下,我想通过写作来计算它:
c(a) = c(a) + b
Run Code Online (Sandbox Code Playgroud)
但显然它不会给我相同的结果,因为我必须多次重新计算相同索引的值,所以这种矢量化方式不起作用。另外,如果这很重要,我正在使用 Matlab 或 Octave。
非常感谢您的帮助,我不确定是否可以进行矢量化。
编辑:非常感谢您到目前为止的回答。我发现了 accumarray,我以前不知道它,并且也理解了为什么改变 Matlab 和 Octave 之间的 for 循环给了我如此不同的时间。我也更好地理解了我的问题。我举了一个太简单的例子,我认为我可以扩展它,但是,如果 b 是一个矩阵呢?
(让我们暂时忘记 c ):
a = [1 4 2 2 1 3 4 2 3 1]
b =[0.69 -0.41 -0.13 -0.13 -0.42 -0.14 -0.23 -0.17 0.22 -0.24;
0.34 -0.39 -0.36 0.68 -0.66 -0.19 -0.58 0.78 -0.23 0.25;
-0.68 -0.54 0.76 -0.58 0.24 -0.23 -0.44 0.09 0.69 -0.41;
0.11 -0.14 0.32 0.65 0.26 0.82 0.32 0.29 -0.21 -0.13;
-0.94 -0.15 -0.41 -0.56 0.15 0.09 0.38 0.58 0.72 0.45;
0.22 -0.59 -0.11 -0.17 0.52 0.13 -0.51 0.28 0.15 0.19;
0.18 -0.15 0.38 -0.29 -0.87 0.14 -0.13 0.23 -0.92 -0.21;
0.79 -0.35 0.45 -0.28 -0.13 0.95 -0.45 0.35 -0.25 -0.61;
-0.42 0.76 0.15 0.99 -0.84 -0.03 0.27 0.09 0.57 0.64;
0.59 0.82 -0.39 0.13 -0.15 -0.71 -0.84 -0.43 0.93 -0.74]
Run Code Online (Sandbox Code Playgroud)
我现在明白我要做的是每组的 rowSum,鉴于我使用的是 Octave,我不能使用“splitapply”。我试图概括您的答案,但 accumarray 不适用于矩阵,而且我也无法概括 @rahnema1 解决方案。所需的输出是:
[0.34 0.26 -0.93 -0.56 -0.42 -0.76 -0.69 -0.02 1.87 -0.53;
0.22 -1.03 1.53 -0.21 0.37 1.54 -0.57 0.73 0.23 -1.15;
-0.20 0.17 0.04 0.82 -0.32 0.10 -0.24 0.37 0.72 0.83;
0.52 -0.54 0.02 0.39 -1.53 -0.05 -0.71 1.01 -1.15 0.04]
Run Code Online (Sandbox Code Playgroud)
那是“等价于”
[sum(b([1 5 10],:))
sum(b([3 4 8],:))
sum(b([6 9],:))
sum(b([2 7],:))]
Run Code Online (Sandbox Code Playgroud)
非常感谢,如果您认为我应该将其包含在另一个问题中而不是添加编辑,我会这样做。
可以通过以下方式完成accumarray:
a = [1 4 2 2 1 3 4 2 3 1];
b = [0.5 0.2 0.3 0.4 0.1 0.05 0.7 0.3 0.55 0.8];
c = [3 5 7 9];
c(:) = c(:) + accumarray(a(:), b(:));
Run Code Online (Sandbox Code Playgroud)
这会将b定义的组中的值相加a,并将其添加到原始c.
如果b是矩阵,则可以使用
full(sparse(repmat(a, 1, size(b,1)), repelem(1:size(b,2), size(b,1)), b))
Run Code Online (Sandbox Code Playgroud)
或者
accumarray([repmat(a, 1, size(b,1)).' repelem(1:size(b,2), size(b,1)).'], b(:))
Run Code Online (Sandbox Code Playgroud)