Changeset 3269

Show
Ignore:
Timestamp:
01/26/12 21:06:53 (4 months ago)
Author:
erkn
Message:

Add MPI support + minor cleanup

Location:
branches/mcxtrace-1.0/src/mcrun2
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • branches/mcxtrace-1.0/src/mcrun2/main.py

    r3268 r3269  
    11#!/usr/bin/env python2.6 
    22 
    3 import os.path 
    43import logging 
    54 
    6 from os.path import isfile, isdir, abspath, dirname, basename 
     5from os.path import isfile, isdir, abspath, dirname 
    76from optparse import OptionParser, OptionGroup, OptionValueError 
    87 
     
    1817        ''' value must be acceptable ''' 
    1918        if not accept(value): 
    20             raise OptionValueError('option %s: %s (was: "%s")' % (option, msg, value)) 
     19            raise OptionValueError('option %s: %s (was: "%s")' % \ 
     20                                   (option, msg, value)) 
    2121        # Update parser with accepted value 
    2222        setattr(parser.values, option.dest, value) 
     
    120120    # Data options 
    121121    dir_exists = lambda path: isdir(abspath(path)) 
    122     check_dir = build_checker(dir_exists, 'invalid path') 
    123122    def check_file(exist=True): 
    124123        ''' Validate the path to a file ''' 
     
    164163 
    165164 
     165def expand_options(options): 
     166    ''' Add extra options based on previous choices ''' 
     167    if options.mpi > 0: 
     168        options.use_mpi = True 
     169        options.cc = 'mpicc' 
     170    else: 
     171        options.use_mpi = False 
     172        options.cc = 'gcc' 
     173 
     174 
    166175def main(): 
    167176    ''' Main routine ''' 
     
    170179    formatter = logging.Formatter('%(asctime)s - %(message)s') 
    171180 
    172     ch = logging.StreamHandler() 
    173     ch.setLevel(logging.INFO) 
    174     ch.setFormatter(formatter) 
     181    handler = logging.StreamHandler() 
     182    handler.setLevel(logging.INFO) 
     183    handler.setFormatter(formatter) 
    175184 
    176185    LOG.setLevel(logging.DEBUG) 
    177     LOG.addHandler(ch) 
     186    LOG.addHandler(handler) 
    178187 
    179188    # Add options 
     
    188197    (options, args) = parser.parse_args() 
    189198    parser.destroy() 
     199    expand_options(options) 
    190200 
    191201    if options.verbose: 
    192         ch.setLevel(logging.DEBUG) 
     202        handler.setLevel(logging.DEBUG) 
    193203 
    194204    # Extract instrument and parameters 
    195205    if len(args) == 0: 
    196206        raise OptionValueError('No instrument file specified.') 
    197     instr = args[0] 
    198     params = args[1:] 
     207    options.instr = args[0] 
     208    options.params = args[1:] 
    199209 
    200210    # Run McStas 
    201     mcstas = McStas(instr) 
     211    mcstas = McStas(options.instr) 
    202212    mcstas.prepare(options) 
    203     mcstas.run(options) 
     213    mcstas.run() 
    204214 
    205215 
  • branches/mcxtrace-1.0/src/mcrun2/mcstas.py

    r3266 r3269  
    1313 
    1414def modified(path): 
     15    ''' Get modification time of path in seconds ''' 
    1516    return os.stat(path).st_mtime 
    1617 
    1718 
    1819class ProcessException(Exception): 
     20    ''' Exception/error in external process ''' 
     21 
    1922    def __init__(self, executable, args, retval): 
    2023        Exception.__init__(self) 
     
    2932 
    3033class Process: 
     34    ''' An external process ''' 
     35 
    3136    def __init__(self, executable): 
    3237        self.executable = executable 
    3338 
    3439    def run(self, args=None): 
     40        ''' Run external process with args ''' 
     41 
    3542        if args is None: 
    3643            args = [] 
     
    3845        # Run executable 
    3946        LOG.debug('CMD: %s %s' % (self.executable, args)) 
    40         fd = Popen([self.executable] + args, 
    41                    stdout=None, 
    42                    stderr=None) 
    43         stdout, stderr = fd.communicate() 
     47        fid = Popen([self.executable] + args, 
     48                    stdout=None, 
     49                    stderr=None) 
     50        stdout, stderr = fid.communicate() 
    4451 
    4552        # Check if process terminated correctly 
    46         retval = fd.wait() 
     53        retval = fid.wait() 
    4754        if retval != 0: 
    4855            raise ProcessException(self.executable, args, retval) 
     
    5259 
    5360class McStas: 
     61    ''' McStas instrument ''' 
     62 
    5463    def __init__(self, instrument_file): 
    5564        if not isfile(instrument_file): 
     
    5766        self.path = instrument_file 
    5867        self.name = splitext(basename(self.path))[0] 
     68        self.options = None 
    5969 
    6070        # Setup paths 
     
    6979    def prepare(self, options): 
    7080        ''' Prepare for simultation run ''' 
     81        self.options = options 
     82 
     83        # Use mpi? 
     84        mpi = options.use_mpi 
     85 
     86        self.binpath += (mpi and '-mpi' or '') 
     87 
    7188        # Check if instrument code has changed 
    7289        if not options.force_compile and isfile(self.binpath) \ 
     
    7491            LOG.info('Using existing binary: %s' % self.binpath) 
    7592            return  # skip 
     93        LOG.info('Recompiling: %s' % self.binpath) 
    7694 
    77         # Proceed with generation and compilation 
    78         LOG.info('Recompiling: %s' % self.binpath) 
     95        # Generate C-code 
    7996        Process('mcstas').run(['-o', self.cpath, self.path]) 
    8097 
    81         cc = 'gcc' 
     98        # Setup cflags 
     99        cflags = [ 
     100            '-lm',  # math library 
     101            options.no_cflags and '-O0' or '-O2',  # optimizing flags 
     102            mpi and '-DUSE_MPI' or '-D',  # MPI 
     103        ] 
    82104 
    83105        # Compiler optimisation 
    84         opt = options.no_cflags and '-O0' or '-O2' 
    85         args = ['-o', self.binpath, opt, '-lm', self.cpath] 
     106        args = ['-o', self.binpath] + cflags + [self.cpath] 
    86107 
    87         Process(cc).run(args) 
     108        Process(options.cc).run(args) 
    88109 
    89110 
    90     def run(self, options): 
     111    def run(self): 
    91112        ''' Run simulation ''' 
    92113        args = [] 
     114        options = self.options 
    93115        print repr(options) 
    94116 
    95         # Handle proxy options, pass through 
     117        mpi = self.options.use_mpi 
     118 
     119        # Handle proxy options with values 
    96120        proxy_opts_val = ['seed', 'ncount', 'dir', 'file', 'format'] 
    97         proxy_opts_flags = ['trace', 'gravitation', 'data-only', 
    98                             'no-output-files', 'info'] 
    99  
    100121        for opt in proxy_opts_val: 
    101122            val = getattr(options, opt.replace('-', '_')) 
     
    103124                args.extend(['--%s' % opt, str(val)]) 
    104125 
     126        # Handle proxy options without values (flags) 
     127        proxy_opts_flags = ['trace', 'gravitation', 'data-only', 
     128                            'no-output-files', 'info'] 
    105129        for opt in proxy_opts_flags: 
    106130            val = getattr(options, opt.replace('-', '_')) 
     
    108132                args.append('--%s' % opt) 
    109133 
     134        # Add parameters last 
     135        args += options.params 
     136 
    110137        # Run McStas 
    111         LOG.info('Running: %s' % self.binpath) 
    112         Process(self.binpath).run(args) 
     138        if not mpi: 
     139            LOG.info('Running: %s' % self.binpath) 
     140            Process(self.binpath).run(args) 
     141        else: 
     142            LOG.info('Running via MPI: %s' % self.binpath) 
     143            mpi_args = ['-np', str(options.mpi), self.binpath] 
     144            mpi_args += args 
     145            Process('mpirun').run(mpi_args) 
    113146 
    114147 
    115148    def cleanup(self): 
     149        ''' Remove temporary files ''' 
    116150        for path in (self.cpath,): 
    117151            try: 
    118152                os.remove(path) 
    119153            except OSError: 
    120                 pass # file not found 
     154                pass  # file not found 
    121155 
    122156        os.rmdir(self.dir) 
    123157 
    124  
    125 if __name__ == '__main__': 
    126     formatter = logging.Formatter('%(asctime)s - %(message)s') 
    127  
    128     ch = logging.StreamHandler() 
    129     ch.setLevel(logging.INFO) 
    130     ch.setFormatter(formatter) 
    131  
    132     LOG.setLevel(logging.DEBUG) 
    133     LOG.addHandler(ch) 
    134  
    135     m = McStas('/home/jos/diku/McCode/trunk/src/McStasTest/examples/ILL_D4.instr') 
    136     m.prepare() 
    137     m.run()