For large $n\times n$ symmetric matrices $T,$ where $n\approx10000,$ is there an efficient way of computing the total sum $S$ of its entries in Mathematica without having to loop over all its entries? i.e. $S=\sum_{i,j} t_{ij},$ for every $i,j.$ The fact that it's symmetric does help already as we only have to sum over one of its triangular parts.
Asked
Active
Viewed 1,214 times
2 Answers
6
You can use Total. Here's a matrix of the given size:
m = RandomReal[1, {10000, 10000}];
And here's the output of Total:
Total[m, 2] // AbsoluteTiming
{0.041005, 4.99984*10^7}
Carl Woll
- 130,679
- 6
- 243
- 355
-
-
In general, Mathematica is set up that we almost never want to code loops (like "for" loops) when we can instead use built-in functions that treat lists and arrays as holistic objects. – Greg Martin Oct 27 '19 at 05:09
5
Here is another solution that performs similarly to Total:
v = ConstantArray[1, 10000];
m = RandomReal[1, {10000, 10000}];
v.m.v // AbsoluteTiming
{0.040816, 4.99968*10^7}
Total[m, 2] // AbsoluteTiming
{0.041774, 4.99968*10^7}
The reason that these solutions are fast is that they use vectorization. Using Compile is not quite as fast, especially not when compiling loops:
sum = Compile[{{m, _Real, 2}},
Sum[Compile`GetElement[m, i, j], {i, Length[m]}, {j, Length[m]}],
CompilationTarget -> "C",
RuntimeOptions -> "Speed"
];
sum[m] // AbsoluteTiming
{0.092583, 5.00016*10^7}
sum = Compile[{{m, _Real, 2}}, Module[{tot},
tot = 0.;
Do[
Do[
tot += Compile`GetElement[m, i, j],
{i, j + 1, Length[m]}
],
{j, Length[m] - 1}
];
2 tot + Tr[m]
],
CompilationTarget -> "C",
RuntimeOptions -> "Speed"
]
sum[m] // AbsoluteTiming
{1.1837, 4.99976*10^7}
C. E.
- 70,533
- 6
- 140
- 264
-
Ah quite neat, thanks! I tried that but I was transposing the left
v(because I was calculating $\mathbf{v}^T \mathbf{m} \mathbf{v}$) and it kept giving an error. – Oct 26 '19 at 16:40 -
@user929304 Mathematica does not distinguish between row vectors and column vectors, so the transpose is not used for such things, unlike in some software like MATLAB. Here is a good post about it. – C. E. Oct 26 '19 at 16:50
-
Thanks a lot, explains my confusion, and very much appreciate the added approaches, learned a lot! – Oct 27 '19 at 11:22
Sum[m[[i, j]], {i, 10000}, {j, 10000}](which may look like a reasonable solution, depending on your background) takes 38 seconds to compute the same answer. – C. E. Oct 26 '19 at 22:30tot = 0; Do[ Do[ tot += m[[i, j]], {i, j, 10} ], {j, 10} ] tot = 2 tot - Total@Diagonal[m]This is clearly preferable to looping over all the elements. Only it turns out that the most efficient way to do this, by far, is not to loop at all, but to use vectorization instead. – C. E. Oct 26 '19 at 22:40Total[Flatten[m]]takes one second, and is not tricky code but not EFFICIENT by needing the whole matrix! – Bill Oct 27 '19 at 01:40