Bill Allombert on Sun, 13 Oct 2013 14:28:37 +0200


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Branch bill-mt for parallel pari updated


Dear PARI developers,

I have updated the GIT branch bill-mt for parallel pari.
This branch support three kind of parallelism:
- POSIX threads: do
./Configure --mt=pthread 
- MPI (for clusters)
./Configure --mt=mpi
- No parallelism:
./Configure --mt=single

The following parallel GP functions are available:
parapply, pareval, parsum, parvector

Code evaluated in parallel must not access global variables and local variables
declared with local(), and must be free of side effect.

The following new defaults are available:
nbthreads: number of threads to use
threadsize: the stack of the PARI size used by each threads

An example file is provided: examples/pari-mt.gp

An new declaration is available:
inline(var)
This declares that var should be inlined in each functions, with the value
of var at the time the function is created.
This allows to create functions that are not stored in global variables,
which is necessar for parallel code.

I will give an example:
You want to compute this in parallel:
--
sinc(x)=if(x,sin(x)/x,1)
fun(a)=intnum(x=0,a,sinc(x))
apply(fun,[1..100])
--
If you do
--
sinc(x)=if(x,sin(x)/x,1)
fun(a)=intnum(x=0,a,sinc(x))
parapply(fun,[1..100])
--
it fails with
  *** parapply: mt: global variable not supported :sinc.
since parallel code cannot use global variables.
What you can do is
--
inline(sinc);
sinc(x)=if(x,sin(x)/x,1);
fun(a)=intnum(x=0,a,sinc(x));
parapply(fun,[1..100])
--
which works since now sinc is inlined inside fun.

NB: if you use parvector instead of parapply as in
parvector(100,i,fun(i))
you will have to declare fun as inline, too.

Sometime it is convenient to interrupt a parallel computation when one of
the thread has found the result we sought. This can be done using
the error/iferr mechanism. 

For example, let says we want to find an elliptic curve of prime order over
F_p for some p:

--
inline(test);
test(p)=a->my(E=ellinit([1,a],p));if(isprime(ellcard(E)),error(a))
getcurve(p)=
{
  iferr(parapply(test(p),[1..1000]),err
    ,component(err,1)
    ,errname(err)=="e_USER");
}
--
? getcurve(nextprime(2^120))
%4 = [200]
? E=ellinit([1,200],nextprime(2^120));
? ellcard(E)
%5 = 1329227995784915874132467290876997467
? isprime(%)
%6 = 1

The mechanism of throwing an error to interrupt the parallel computation is a bit
ugly but works really well.
Maybe I could add a dedicated function.

Cheers,
Bill.