Bill Allombert on Sat, 23 Jun 2012 18:05:41 +0200


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

Re: A question about memory and garbage collection


On Sun, Jun 24, 2012 at 01:14:05AM +1000, Alasdair McAndrew wrote:
> I am testing some prng routines, and using PARI to speed up the
> computations.
> 
> My basic routine contains something like
> 
> int main(int argc, char *argv[])
> {
>   pari_init(1000000,0);
>   n = gp_read_str(argv[1]);
>   i = gen_0;
>   do
>     {
>       GEN t = prng();
>     }
>   while (mpcmp(i,n)<0);
> 
>   pari_close();
>   return 0;
> }
> 
> Here prng() is a function which returns a GEN.  Basically it takes a value
> x, does some computations (using a few auxiliary variables), and returns an
> updated value.  It may do this 10^12 times.  Clearly I need to have some
> sort of memory management: once a value x is updated and used to create the
> next value, it is needed no longer.  So I need some way of removing the
> previous value of x so that the stack doesn't overflow.
> 
> Here's an example of the sort of prng() I might use (I'm not actually using
> this one, but you get the idea):
> 
> GEN prng(void)
> {
>   y = Fp_pow(x,7,p);
>   x = y;
>   return(x);
> }

Your example is not very enlightening... What matter is what object you still
need available at each point. In your example nothing need to be preserved
since no value are used.

You should consider using the program GP2C to generate example code for you.
(Try the flag -g).

Let assume your example is actually:

GEN prng(GEN x, GEN p)
{
  return Fp_pow(x,7,p);
}

int main(int argc, char *argv[])
{
  pari_init(1000000,0);
  GEN n = gp_read_str(argv[1]);
  long i=0;
  GEN x = gen_2;
  do
  {
    x = prng(x);
    i++;
  }
  while (cmpsi(i,n)<0);

  pari_close();
  return 0;
}

Here you want to forget about the old value of x while keeping prng(x);

int main(int argc, char *argv[])
{
  pari_sp av;
  pari_init(1000000,0);
  GEN n = gp_read_str(argv[1]);
  long i=0;
  GEN x, p = stoi(1009);
  av = avma;
  x = gen_2:
  do
  {
    x = gerepileupto(av, prng(x));
    i++;
  }
  while (cmpsi(i,n)<0);

  pari_close();
  return 0;
}

gerepileupto(av, y) remove everything created between the call to av = avma;
and gerepileupto while returning a copy of y (saving y from oblivion).

Cheers,
Bill.