2
$\begingroup$

after I got such a great response for my first question on this site, I'm very encouraged to asked my second one!

So here it is, very generally: To speed up a "row-wise" (i.e. 1D) operation on a matrix, I tried to use the ParallelTable instead of the Table function. I don't know why, but due to some reason this fails. It seems that the expression inside the ParallelTable gets not evaluated correctly. Maybe somebody knows why?

I start with my functions: The "FftShift1D" is simply to reorder the result of the Fourier function. The "eqn" function is just an arbitrary function to test the parallelization later on.

ClearAll["Global`*"]

FftShift1D[x_?VectorQ] := 
 Module[{n = Ceiling[Length[x]/2]}, RotateRight[x, n]]

eqn[kx_?MachineNumberQ, y_?MachineNumberQ] := 
 2/3 Exp[-I kx] (1 + I kx) + Sin[y]/y

Now, I create a matrix with the help of the "Table" function. The following definitions are used to change the size of the matrix easily.

kxmin = -100; kxmax = 100; kxdiv = 2000; kxinc = (kxmax - 
    kxmin)/(kxdiv - 1);
zmin = -5; zmax = 5; zdiv = 200; zinc = (zmax - zmin)/(zdiv - 1);

kspace = Table[
   eqn[kx, z], {kx, kxmin, kxmax, kxinc}, {z, zmin, zmax, zinc}];

So I want to apply a FFT only on the "kx" direction, i.e. there are "zdiv" times a 1D FFT. This is how I've done this "serially":

res = Table[
   FftShift1D[Fourier[N[
   kspace[[;; kxdiv, i]]
]]], {i, 1, zdiv}];

This works properly, and it results in "res" being a matrix (or Table, however you like to call it) with the same size as "kspace". Changing now to

SetSharedVariable[kxmin, kxmax, kxdiv, kxinc, zmin, zmax, zdiv, zinc, 
  kspace, res];

res = ParallelTable[
   FftShift1D[Fourier[N[
   kspace[[;; kxdiv, i]]
]]], {i, 1, zdiv}];

fails with the following messages:

Fourier::fftl: Argument {eqn[-100.,-5.],eqn[-99.8999,-5.],
eqn[-99.7999,-5.],<<6>>,eqn[-99.0995,-5.],<<1990>>}
is not a nonempty list or rectangular array of numeric quantities.

You see, that although I call "N", the "eqn" gets not evaluated properly... Does someone knows why? Kind regards Clemens

PS: I've found something not completely unlike my problem here, but not as in ParallelTable and Table do not give same result my problem does not change when using Parellelize[Table[...]] instead of ParellelTable[...]

$\endgroup$
4
  • $\begingroup$ you probably need to distribute definitions. $\endgroup$
    – acl
    Mar 17, 2013 at 11:36
  • $\begingroup$ @acl I don't do much in parallel; with DistributeDefinitions as used in my answer the code apparently never finishes. Does it work on your machine? $\endgroup$
    – Mr.Wizard
    Mar 17, 2013 at 11:42
  • $\begingroup$ @Mr.Wizard if I do ParallelTable[FftShift1D[Fourier[N[kspace[[;; 10, i]]]]], {i, 1, 2}] (ie, decrease the limits) it does work properly (ie gives same as Table). This on 9.0.1. If Clemens still has not worked out what is going on, I'll give it a shot later today (I need to do something first). Would be nice to have a minimal example by the way. $\endgroup$
    – acl
    Mar 17, 2013 at 15:55
  • $\begingroup$ There is probably very limited benefit in using the Parallel` package for this since Fourier is already multithreaded via the MKL. Please see also this question, which perhaps is not the most clearly titled. $\endgroup$ Mar 17, 2013 at 22:16

1 Answer 1

6
$\begingroup$

In version 7 you will need to use use DistributeDefinitions for FftShift1D and eqn. Furthermore, as Szabolcs kindly explains in the comments you should be using DistributeDefinitions for the other symbols as well, instead of SetSharedVariable:

DistributeDefinitions[FftShift1D, eqn, kxmin, kxmax,
  kxdiv, kxinc, zmin, zmax, zdiv, zinc, kspace];

With this your ParallelTable runs, and slightly faster than the non-parallel version, but not by a lot. A modified suggestion of Szabolcs's proves considerably faster:

res2 = ParallelMap[FftShift1D @ Fourier @ N @ # &, kspace\[Transpose]];
$\endgroup$
7
  • $\begingroup$ Yes, it works, but it's really very slow... $\endgroup$
    – Clemens
    Mar 17, 2013 at 13:06
  • $\begingroup$ @Clemens yes, very slow. I'm hoping that someone who actually uses the Parallel tools will stop by with an answer. I typically just leave slow computations running in the background and therefore I don't want them using all the cores, so I've never really learned to use the Parallel tools. Sorry I can't be of more help at the moment. :-/ $\endgroup$
    – Mr.Wizard
    Mar 17, 2013 at 13:12
  • 1
    $\begingroup$ @Clemens Using SetSharedVariable will force all those variables to be accessed through the main kernel. By making all these variables shared, you nullify all advantages of parallelization. You should use DistributeDefinitions for these, not SetSharedVariable, then precompute the quantity N[ kspace[[;; kxdiv, i]]] on the main kernel, then finally ParallelMap your function. Unfortunately I don't have access to a multicore machine at this moment, so I coulnd't actually test this. $\endgroup$
    – Szabolcs
    Mar 17, 2013 at 16:15
  • $\begingroup$ @Szabolcs That makes a lot of sense; thanks. $\endgroup$
    – Mr.Wizard
    Mar 17, 2013 at 18:17
  • 1
    $\begingroup$ @Szabolcs actually, the way his code is written all the time is spent on the N operation as that triggers the evaluation of eqn. I did however realize he was doing a complicated transpose and replaced it with Transpose. $\endgroup$
    – Mr.Wizard
    Mar 17, 2013 at 18:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.