Performance matlab中矩阵元素求和的高效(最快)方法

Performance matlab中矩阵元素求和的高效(最快)方法,performance,matlab,matrix,sum,Performance,Matlab,Matrix,Sum,让矩阵AsayA=magic(100)。我见过两种计算矩阵A所有元素之和的方法 sumOfA = sum(sum(A)); 或 其中一个比另一个更快(或更好地练习)?如果是,是哪一个?或者它们都一样快?性能方面,我认为两者非常相似(假设是最新的MATLAB版本)。下面是使用该功能进行的快速测试: function sumTest() M = randn(5000); timeit( @() func1(M) ) timeit( @() func2(M) ) end fu

让矩阵
A
say
A=magic(100)。我见过两种计算矩阵
A
所有元素之和的方法

sumOfA = sum(sum(A));


其中一个比另一个更快(或更好地练习)?如果是,是哪一个?或者它们都一样快?

性能方面,我认为两者非常相似(假设是最新的MATLAB版本)。下面是使用该功能进行的快速测试:

function sumTest()
    M = randn(5000);
    timeit( @() func1(M) )
    timeit( @() func2(M) )
end
function v = func1(A)
    v = sum(A(:));
end
function v = func2(A)
    v = sum(sum(A));
end
结果是:

>> sumTest
ans =
    0.0020917
ans =
    0.0017159
我担心的是浮点问题。例如:

>> M = randn(1000);
>> abs( sum(M(:)) - sum(sum(M)) )
ans =
   3.9108e-11

对于较大的矩阵,误差幅度会增加

您似乎无法决定性能或浮点精度是否更重要

如果浮点精度是最重要的精度,那么您将分离正负元素,对每个段进行排序。然后按绝对值递增的顺序求和。是的,我知道,这项工作比任何人都要多,而且可能是浪费时间

取而代之的是,使用足够的精度,这样所产生的任何错误都是无关紧要的。在测试等方面使用良好的数值实践,这样就不会产生任何问题

随着时间的推移,对于NxM阵列

求和(A(:)将需要N*M-1个加法

求和(求和(A))需要(N-1)*M+M-1=N*M-1加法

这两种方法都需要相同数量的加法,因此对于大型数组,即使解释器不够聪明,无法识别它们都是同一个op,谁在乎呢

这根本不是问题。别为了这事而大惊小怪

编辑:对于Amro关于一种方法比另一种方法的错误的评论,您几乎无法控制。添加将以不同的顺序进行,但无法保证哪个顺序更好

A = randn(1000);
format long g
这两种解决方案非常接近。事实上,与每股收益相比,这一差异并不显著

sum(A(:))
ans =
          945.760668102446

sum(sum(A))
ans =
          945.760668102449

sum(sum(A)) - sum(A(:))
ans =
      2.72848410531878e-12

eps(sum(A(:)))
ans =
      1.13686837721616e-13
假设您选择了我提到的隔离和排序技巧。请注意,负极和正极部件将足够大,从而导致精度损失

sum(sort(A(A<0),'descend'))
ans =
          -398276.24754782

sum(sort(A(A<0),'descend')) + sum(sort(A(A>=0),'ascend'))
ans =
            945.7606681037
甚至在这些测试中也出现了一个有趣的问题。由于测试是在随机(正常)阵列上进行的,是否会出现问题?本质上,我们可以把sum(A(:)看作是一次随机行走,一次醉汉的行走。但是考虑和(和(a))。总和(A)的每个元素(即内部总和)本身就是1000个正常偏差的总和。看看其中的几个:

sum(A)
ans =
  Columns 1 through 6
         -32.6319600960983          36.8984589766173          38.2749084367497          27.3297721091922          30.5600109446534          -59.039228262402
  Columns 7 through 12
          3.82231962760523          4.11017616179294         -68.1497901792032          35.4196443983385          7.05786623564426         -27.1215387236418
  Columns 13 through 18
当我们把它们加起来时,就会失去精确度。因此,作为sum(A(:)的运算可能会稍微精确一些。是这样吗?如果我们使用更高的累积精度会怎么样?首先,我将使用双精度对列进行求和,然后将其转换为十进制精度的25位数字,并对行进行求和。(我在这里只显示了20个数字,留下5个隐藏的数字作为保护数字。)

或者,立即转换为25位精度,然后对结果求和

sum(hpf(A(:))
945.76066810244749807

所以两种形式的双精度在这里都是同样错误的,方向相反。最后,这一切都是毫无意义的,因为我所展示的任何替代方案都比简单的变量sum(A(:)或sum(A))要耗时得多。只要选择其中一个,别担心。

我认为一个简单的理解方法是在代码的第一个和最后一个应用“tic\utoc”函数

tic
A = randn(5000);
format long g
sum(A(:));
toc
但当你使用randn函数时,它的元素是随机的,计算的时间是有限的 在每个周期CPU计算中不同。
最好使用一个具有如此多元素的唯一矩阵来比较计算时间。

每个方法都必须遍历矩阵的每个元素。因此,当涉及到复杂性时,它们是一样的。我建议您使用不同的方法制作两个脚本,巨大的矩阵,并计算它们的执行时间。从长远来看,我会说第二个更好,因为它不涉及内存分配操作,但正如我所说的,这是一个长远的目标,我可能遗漏了一些东西。你可以使用Matlab的
tic
toc
函数来执行实验。我做了一个快速测试,速度没有差异。
sum(A(:)
的一个优点是,您不需要知道
A
有多少维度;它适用于任意数量的DIM。所以说到浮点问题,哪种方法更可取?没有办法知道哪种方法会给出更好的答案。这两个结果在低阶位中是完全随机的。这完全取决于数字的添加顺序,这是matlab和您都不会担心的。谢谢,回答得很好。这就是我问这个问题的原因:我有两段代码,它们都做相同的思考(总是产生相同的结果)。但是其中一个跑的时间是另一个的两倍。它们之间几乎没有什么区别,它们对矩阵求和的方式就是其中之一。我猜这可能是造成性能差异的部分。我得去别的地方看看。性能在这里非常重要,因为它是大数据上的优化问题。。。我宁愿等一天结果,也不愿等两天。@drasto您试过分析代码了吗?你说“他们之间几乎没有什么不同”,这只是其中之一。你看过其他人吗?如果“大数据优化问题”中的“瓶颈”是矩阵元素的求和,我会非常惊讶,不,我会感到震惊。我对
sum(sum(a))
的一个担心是,解释器是否决定分配一个临时矩阵来保存内部
sum
的结果。如果你在一个循环中这样做,并且你有很多的列,分配和释放临时矩阵会变成一个真正的性能拖动。Matlab JIT有可能会对此进行优化,但我也看到过类似的情况,但事实并非如此。@woodchips:+1一如既往的好答案@斯福曼:sum(hpf(sum(A))) ans = 945.76066810244807408
sum(hpf(A(:))
945.76066810244749807
tic
A = randn(5000);
format long g
sum(A(:));
toc