# Parallelize matrix operations

I'm trying to reduce to a minimum the time of some matrix operations.

When I don't parallelize and write the code in the most compact form I get the operation done in around 1sec (is this good? the matrices are around 1000x1000 machine precision numbers):

In[494]:= newtotd = AbsoluteTiming[
fullmat[[nodenumb]]/tempmat
][[1]]

Out[494]= 1.006177


But if I try to have mathematica parallelizing it (4 cores) the performance is much worse:

In[492]:= newtotd = AbsoluteTiming[
Parallelize[fullmat[[nodenumb]]/tempmat]
][[1]]

Out[492]= 2.362393


I also tried to write the code in a more explicit form, with Table (this actually gives the transposed "newtotd" matrix as a result, which is even better for me):

In[497]:= newtotd =
AbsoluteTiming[Table[
fullmat[[nodenumb, k]]/tempmat[[j, k]],
{j, Length[tempmat]}, {k, Length[tempmat]}]][[1]]

Out[497]= 3.154871


and as expected it's even worse. But I was hoping that ParallelTable would do better. I was wrong, I aborted the evaluation after 1 minute:

In[498]:= newtotd =
AbsoluteTiming[ParallelTable[
fullmat[[nodenumb, k]]/tempmat[[j, k]],
{j, Length[products]}, {k, Length[products]}]][[1]]

Out[498]= \$Aborted


What's happening? I guess it should be something related to passing the matrices back and forth between the kernels, but how do I avoid it?

(of course tempmat has no 0. entries)

(EDIT) The operation described in the first piece of code takes so long because there are lots of Infinity entries in the tempmat matrix. If I replace them with 1. and keep track of their position, I can then change the corresponding entries in the resulting matrix to be 0., but still this operation takes much longer than I can accept:

In[154]:= (*Get the position of all Infinity entries in tempmat*)

infpos = Position[tempmat, Infinity];
(*Replace them with 1.*)

Table[tempmat[[infpos[[i, 1]], infpos[[i, 2]]]] = 1., {i,
Length[infpos]}];
AbsoluteTiming[
newtotd = fullmat[[nodenumb]]/tempmat
][[1]]
(*Set the corresponding entries in the newtotd matrix to be 0. as \
they should if I the Infinties weren't removed*)
AbsoluteTiming[
Table[newtotd[[infpos[[i, 1]], infpos[[i, 2]]]] = 0., {i,
Length[infpos]}];
][[1]]

Out[156]= 0.046682

Out[157]= 2.423674


Perhaps you can think of a faster way to set all the "infpos" entries to 0 at the end?

-
I doubt you can speed up something as simple as a machine-precision division operation which is likely much faster than the communication required for parallelism. In that sense I believe this is a duplicate of (31560) – Mr.Wizard Sep 10 '13 at 11:47
However, looking at your timings somethings seems to be wrong unless you are using a very old machine (unlikely if you have four cores I think). I can divide one 1000x1000 matrix by another in an average timing of 0.0046 seconds. Perhaps you could provide a minimal working example of the code that takes one second to run? – Mr.Wizard Sep 10 '13 at 11:52

These types of matrix operations already use multiple CPU cores efficiently:

In[1]:=
a = RandomReal[1, {3000, 3000}];
b = RandomReal[1, {3000, 3000}];

In[3]:= AbsoluteTiming@Timing[a/b;]
Out[3]= {0.087828, {0.350962, Null}}


Please see here on why the timing difference demonstrates this.

Another things to note is that Parallelize will not (and cannot) parallelize any code, only a few types of constructs such as Table, Map, etc. Most of these already have parallel counterparts: ParallelTable, ParallelMap. The type of parallelization that the parallel computing tools provide is not nearly as efficient as the built-in matrix operations.

-