Changeset 306 for trunk/src/random.py

Show
Ignore:
Timestamp:
04/24/08 15:38:32 (5 years ago)
Author:
apdavison
Message:

The NumpyRNG class now has some extra options for running parallel simulations. If parallel_safe is True (and if the MPI rank and number of processes are correctly supplied), then the sequence of random numbers seen by the simulation script should be independent of the number of MPI processes (although not yet the number of threads).

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/random.py

    r275 r306  
    5656    """Wrapper for the numpy.random.RandomState class (Mersenne Twister PRNG).""" 
    5757     
    58     def __init__(self, seed=None): 
     58    def __init__(self, seed=None, rank=0, num_processes=1, parallel_safe=False): 
    5959        AbstractRNG.__init__(self, seed) 
    6060        self.rng = numpy.random.RandomState() 
     
    6363        else: 
    6464            self.rng.seed() 
     65        self.rank = rank # MPI rank 
     66        self.num_processes = num_processes # total number of MPI processes 
     67        self.parallel_safe = parallel_safe 
    6568             
    6669    def __getattr__(self, name): 
     
    7275         
    7376        If n is 1, return a float, if n > 1, return a numpy array, 
    74         if n < 0, raise an Exception.""" 
     77        if n < 0, raise an Exception."""       
    7578        if n == 0: 
    76             return numpy.random.rand(0) # We return an empty array 
    77         if n > 0: 
    78             return getattr(self.rng, distribution)(size=n, *parameters) 
     79            rarr = numpy.random.rand(0) # We return an empty array 
     80        elif n > 0: 
     81            if self.num_processes > 1 and not self.parallel_safe: 
     82                # n is the number for the whole model, so if we do not care about 
     83                # having exactly the same random numbers independent of the 
     84                # number of processors (m), we only need generate n/m+1 per node 
     85                # (assuming round-robin distribution of cells between processors) 
     86                n = n/self.num_processes + 1  
     87            rarr = getattr(self.rng, distribution)(size=n, *parameters) 
    7988        #elif n == 1: 
    80         #    return getattr(self.rng, distribution)(size=1, *parameters)[0] 
     89        #    rarr = getattr(self.rng, distribution)(size=1, *parameters)[0] 
    8190        else: 
    8291            raise ValueError, "The sample number must be positive" 
    83  
     92        if self.parallel_safe and self.num_processes > 1: 
     93            # strip out the random numbers that should be used on other processors 
     94            rarr = rarr[numpy.arange(self.rank, len(rarr), self.num_processes)] 
     95        return rarr 
    8496 
    8597class GSLRNG(AbstractRNG):