Calculating a multiplication of large number of matrices takes a long time [duplicate]

I have a multiplication of matrices, say

M1.G1.M2.G2.....Mn.Gn, here n may reach 100. M and G are 4 4 matrices and their elements are function of s. Mathematica takes so long to perform this multiplication. However, if I divided it such that p1=M1.G1.M2.G2...M10.G10; P2=M11.G11....M20.G20 . . p10=M91.G91....M100.G100;

and evaluate each line separately, it becomes faster?!

• Which version, and which exact syntax? When I evaluate Dot @@ RandomReal[{-1, 1}, {200, 4, 4}] the multiplication is rapid? – Coolwater Jul 19 '15 at 19:19
• version 10, but my matrices's element are function of unkown parameter s – HD2006 Jul 19 '15 at 19:24

With a bit of Partition you can use ParallelMap to spread the Dot over your available kernels.

You have symbolic entries in your matrix but I'll use numeric entries since I don't have access to your equations. A performance gain is realised and I'm hoping it is transferable to your symbolic problem.

mList is taken to be the list of your $M_n$ matrices and gList the list of your $G_n$ matrices.

mList = Table[RandomReal[{0, 1}, {4, 4}], 1000];
gList = Table[RandomReal[{0, 1}, {4, 4}], 1000];


In rif the list are Riffled to get them in order of the Dot operation.

rif = Riffle[mList, gList];


Now on to the interesting part. We want to partition this list so that we have as many sublists as we have Mathematica kernels on the machine. First LaunchKernels is called to load all kernels that the licence allows. This also updates $KernelCount to the number of kernels available; needed for the partitioning. LaunchKernels[]; With[{n = Floor[Length[rif]/$KernelCount]},
prif = Partition[rif, n, n, 1, {}];
]


I have 4 physical cores which with my parallel settings in Mathematica creates a total of 4 kernels.

Now Dot can be mapped in parallel to each of the sublists in prif with ParallelMap. This gives a list of \$KernelCount entries with each entry the result of the Dot of the prif sublist. Dot is Apply'ed (@@) to this list for the final result.

Dot @@ ParallelMap[Apply[Dot, #] &, prif, 1, Method -> "CoarsestGrained"]


This executes in half the time taking 0.0437 seconds while non-parallel Dot@@rif takes 0.894 seconds.

Feedback to Wolfram

One thing I'd like to see is an extension of the Method -> "ItemsPerEvaluation" option. As it is now you can only specify an upper limit to the number of entries in each evaluation. However, many functions require at least 2 parameters as Dot in this question. In order to insure that this happens for the function we are currently forced to do Partition tricks with Apply. Could "ItemsPerEvaluation" be extended to allow for a lower (l) and upper (u) bound as follows.

Method -> "ItemsPerEvaluation" -> {l, u}


With this we could simply the above (removing the partitioning) to either of the following:

ParallelCombine[Dot, rif, Dot, Method -> "ItemsPerEvaluation" -> {2, Automatic}]


or

Dot @@ ParallelMap[Dot, rif, 1, Method -> "ItemsPerEvaluation" -> {2, Automatic}]