特定のサイズの行列で「合計」関数が非常に遅くなるのはなぜですか?それを回避する方法は?[複製]

Dec 03 2020

同じ作業を行うために、3つのメソッド( "Sum"、 "Total @ Table"、および "Do")が使用されています。「Sum」および「Total @ Table」機能は、num = 250で非常に遅くなります(この数値は、コンピューターの状態によって異なる場合があります。私のラップトップはMacBook Pro 2013 Late with 8G DRAMです)。理由とそれを回避する方法を理解したいと思います

timelist = ConstantArray[0, {3, 20}];
Do[
 num = nn*1 + 239;
 mat = RandomReal[{0, 1}, {num, num, 2, 2, 2}];
 timelist[[1, nn]] = 
  Timing[r1 = Sum[mat[[l, 1]] l, {l, 1, num}];][[1]];
 timelist[[2, nn]] = 
  Timing[r2 = Total@Table[mat[[l, 1]] l, {l, 1, num}];][[1]];
 timelist[[3, nn]] = Timing[r3 = ConstantArray[0, Dimensions[r2]];
    Do[r3 = r3 + mat[[l, 1]] l, {l, 1, num}];][[1]];
 (*SameQ[r1,r2,r3]*)
 , {nn, 1, 20}]
ListLinePlot[timelist, DataRange -> {240, 260}, 
 PlotLegends -> {"Sum", "Total@Table", "Do"}, 
 AxesLabel -> {"num", "Seconds"}, ScalingFunctions -> "Log"]

回答

5 MichaelE2 Dec 03 2020 at 16:29

MKLのベクトル化を利用した4番目のアプローチに関するFYI、コメントには長すぎます。(システムのCompileしきい値に関連する主な質問への回答は、@ kglrによって指摘された、250を超えるエントリを合計するときのタイミングの突然の増加で見つかる可能性があります。)

timelist = ConstantArray[0, {4, 20}];
Do[num = nn*1 + 239;
 mat = RandomReal[{0, 1}, {num, num, 2, 2, 2}];
 timelist[[1, nn]] = 
  AbsoluteTiming[r1 = Sum[mat[[l, 1]] l, {l, 1, num}];][[1]];
 timelist[[2, nn]] = 
  AbsoluteTiming[r2 = Total@Table[mat[[l, 1]] l, {l, 1, num}];][[1]];
 timelist[[3, nn]] = 
  AbsoluteTiming[r3 = ConstantArray[0, Dimensions[r2]];
    Do[r3 = r3 + mat[[l, 1]] l, {l, 1, num}];][[1]];
 timelist[[4, nn]] = 
  AbsoluteTiming[r4 =  Total[mat[[All, 1]] Range[num]]; ][[1]],
 {nn, 1, 20}]
ListLinePlot[timelist, DataRange -> {240, 260}, 
 PlotLegends -> {"Sum", "Total@Table", "Do", "Total@vectorized"}, 
 AxesLabel -> {"num", "Seconds"}, ScalingFunctions -> "Log"]

r1 == r2 == r3 == r4
(*  True  *)

私の好みについてAbsoluteTiming:AbsoluteTimingとTimingの違い