Warum wird die "Summen" -Funktion bei einer bestimmten Matrixgröße extrem langsam? Wie vermeide ich das? [Duplikat]

Dec 03 2020

Drei Methoden ("Summe", "Total @ Table" und "Do") wurden verwendet, um dieselbe Arbeit auszuführen. Die Funktionen "Summe" und "Gesamt @ Tabelle" werden bei num = 250 extrem langsam (Diese Zahl kann vom Zustand des Computers abhängen. Mein Laptop ist MacBook Pro 2013 Late mit 8G DRAM). Ich hoffe , den Grund zu verstehen und wie zu VERMEIDEN es

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"]

Antworten

5 MichaelE2 Dec 03 2020 at 16:29

Ein FYI, zu lang für einen Kommentar, bezüglich eines vierten Ansatzes, der die Vektorisierung in der MKL nutzt. (Die Antwort auf die Hauptfrage, die mit Systemschwellenwerten verbunden ist Compile, kann bei der plötzlichen Erhöhung des Timings beim Summieren von über 250 Einträgen gefunden werden , worauf @kglr hingewiesen hat.)

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  *)

In Bezug auf meine Präferenz für AbsoluteTiming: Unterschied zwischen AbsoluteTiming und Timing