Here is the example/problem.
I have a array of $n$ random number.
n = 2000;
p = RandomReal[{0, 9}, n];
I have to create a $n\times n$ sparse matrix with $(i,j)$th element given by this condition
$m_{i,j} = \begin{array}{ll} a(p_i-p_j)&2<|p_i-p_j|<3 \\ b(p_i-p_j)&5<|p_i-p_j|<6 \end{array}$
A brutal way to do it is using If
or Piecewise
f1[x_, y_] := If[2 < Abs[x - y] < 3, a[x-y], If[5 < Abs[x - y] < 6, b[x-y], 0]]
SparseArray@Table[f1[p[[i]], p[[j]]], {i, n}, {j, n}]; // AbsoluteTiming
{24.858066, Null}
f2[x_, y_] := Piecewise[{{a[x-y], 2 < Abs[x - y] < 3}, {b[x-y], 5 < Abs[x - y] < 6}}]
SparseArray@Table[f2[p[[i]], p[[j]]], {i, n}, {j, n}]; // AbsoluteTiming
{26.741343, Null}
And of course Map
works much faster
SparseArray@Partition[
If[2 < # < 3, a[#], If[5 < # < 6, b[#], 0]] & /@
Flatten[Abs[# - p] & /@ p], n]; // AbsoluteTiming
{7.797710, Null}
(I don't know how to use Map
in this kind of 2D array so I combined Flatten
and Partition
.)
However I can Parallelize
the Table
and reduce the time to ~1/8th (I have to use the Workstation in my office) and apparently it looks like the If
will be a winner. ParallelMap
doesn't show similar reduction rate in time.
SparseArray@ParallelTable[f1[p[[i]], p[[j]]], {i, n}, {j, n}]; // AbsoluteTiming
{13.573756, Null}
SparseArray@Partition[
ParallelMap[If[2 < # < 3, a[#], If[5 < # < 6, b[#], 0]] &,
Flatten[Abs[# - p] & /@ p]], n]; // AbsoluteTiming
{8.580731, Null}
So what would be the optimised (to minimise time) way to do the job?
For my actual problem n~10000
and a
and b
are combination of trigonometric and arithmetic functions.