Statistiques
| Révision :

root / ase / parallel.py @ 16

Historique | Voir | Annoter | Télécharger (2,43 ko)

1
import sys
2
import time
3
import atexit
4

    
5

    
6
def paropen(name, mode='r', buffering=0):
7
    """MPI-safe version of open function.
8

9
    In read mode, the file is opened on all nodes.  In write and
10
    append mode, the file is opened on the master only, and /dev/null
11
    is opened on all other nodes.
12
    """
13
    if rank > 0 and mode[0] != 'r':
14
        name = '/dev/null'
15
    return open(name, mode, buffering)
16

    
17

    
18
def parprint(*args, **kwargs):
19
    """MPI save print - prints only from master.
20

21
    Tries to adopt python 3 behaviour.
22
    """
23
    if rank > 0:
24
        return
25
    defaults = { 'end' : '\n',
26
                 'file' : sys.stdout }
27
    for key in defaults:
28
        if not key in kwargs:
29
            kwargs[key] = defaults[key]
30

    
31
    for arg in args[:-1]:
32
        print >> kwargs['file'], arg,
33
    if len(args):
34
        last = args[-1]
35
    else:
36
        last = ''
37
    if kwargs['end'] == '\n':
38
        print last
39
    else:
40
        print last,
41

    
42
# Check for special MPI-enabled Python interpreters:
43
if '_gpaw' in sys.modules:
44
    # http://wiki.fysik.dtu.dk/gpaw
45
    from gpaw.mpi import world
46
    rank = world.rank
47
    size = world.size
48
    barrier = world.barrier
49
elif 'asapparallel3' in sys.modules:
50
    # http://wiki.fysik.dtu.dk/Asap
51
    # We cannot import asap3.mpi here, as that creates an import deadlock
52
    #from asap3.mpi import world
53
    import asapparallel3
54
    world = asapparallel3.Communicator()
55
    rank = world.rank
56
    size = world.size
57
    barrier = world.barrier    
58
elif 'Scientific_mpi' in sys.modules:
59
    # 
60
    from Scientific.MPI import world
61
    rank = world.rank
62
    size = world.size
63
    barrier = world.barrier
64
else:
65
    # This is a standard Python interpreter:
66
    rank = 0
67
    size = 1
68
    world = None
69
    def barrier():
70
        pass
71

    
72

    
73

    
74

    
75
def register_parallel_cleanup_function():
76
    """Call MPI_Abort if python crashes.
77

78
    This will terminate the processes on the other nodes."""
79
        
80
    if size == 1:
81
        return
82

    
83
    def cleanup(sys=sys, time=time, world=world):
84
        error = getattr(sys, 'last_type', None)
85
        if error:
86
            sys.stdout.flush()
87
            sys.stderr.write(('ASE CLEANUP (node %d): %s occurred.  ' +
88
                              'Calling MPI_Abort!\n') % (world.rank, error))
89
            sys.stderr.flush()
90
            # Give other nodes a moment to crash by themselves (perhaps
91
            # producing helpful error messages):
92
            time.sleep(3)
93
            world.abort(42)
94

    
95
    atexit.register(cleanup)