Exemplo n.º 1
0
 def main(self, argv):
     args = self._parse_args(argv)
     proj_ctrl = Project.controller()
     proj = proj_ctrl.selected()
     targ = Target.controller(proj_ctrl.storage).one({'name': args.target})
     if targ is None:
         self.parser.error("A target with name %s does not exist." %
                           args.target)
     app = Application.controller(proj_ctrl.storage).one(
         {'name': args.application})
     if app is None:
         self.parser.error("An application with name %s does not exist." %
                           args.application)
     meas = Measurement.controller(proj_ctrl.storage).one(
         {'name': args.measurement})
     if meas is None:
         self.parser.error("A measurement with name %s does not exist." %
                           args.measurement)
     data = {
         'name': args.name,
         'project': proj.eid,
         'target': targ.eid,
         'application': app.eid,
         'measurement': meas.eid
     }
     return self._create_record(PROJECT_STORAGE, data)
Exemplo n.º 2
0
 def _parse_implicit(self, args):
     targets = set()
     applications = set()
     measurements = set()
     experiments = set()
     targ_ctrl = Target.controller(PROJECT_STORAGE)
     app_ctrl = Application.controller(PROJECT_STORAGE)
     meas_ctrl = Measurement.controller(PROJECT_STORAGE)
     expr_ctrl = Experiment.controller(PROJECT_STORAGE)
     for flag in 'impl_experiment', 'impl_project', 'impl_target', 'impl_application', 'impl_measurement':
         for name in getattr(args, flag, []):
             tar = targ_ctrl.one({"name": name})
             app = app_ctrl.one({"name": name})
             mes = meas_ctrl.one({"name": name})
             expr = expr_ctrl.one({"name": name})
             found = set([tar, app, mes, expr]) - set([None])
             if len(found) > 1:
                 self.parser.error("'%s' is ambiguous. "
                                   "Please use a command line flag to specify configuration type." % name)
             elif len(found) == 0:
                 self.parser.error("'%s' is not an experiment, target, application, or measurement." % name)
             elif tar:
                 targets.add(tar)
             elif app:
                 applications.add(app)
             elif mes:
                 measurements.add(mes)
             elif expr:
                 experiments.add(expr)
     return targets, applications, measurements, experiments
Exemplo n.º 3
0
 def _parse_implicit(self, args, targets, applications, measurements):
     targ_ctrl = Target.controller(PROJECT_STORAGE)
     app_ctrl = Application.controller(PROJECT_STORAGE)
     meas_ctrl = Measurement.controller(PROJECT_STORAGE)
     for flag in 'impl_targets', 'impl_applications', 'impl_measurements':
         for name in getattr(args, flag, []):
             tar = targ_ctrl.one({"name": name})
             app = app_ctrl.one({"name": name})
             mes = meas_ctrl.one({"name": name})
             tam = set([tar, app, mes]) - set([None])
             if len(tam) > 1:
                 self.parser.error(
                     "'%s' is ambiguous.  Please use --target, --application,"
                     " or --measurement to specify configuration type" %
                     name)
             elif len(tam) == 0:
                 self.parser.error(
                     "'%s' is not a target, application, or measurement" %
                     name)
             elif tar:
                 targets.add(tar)
             elif app:
                 applications.add(app)
             elif mes:
                 measurements.add(mes)
Exemplo n.º 4
0
 def _parse_implicit(self, args):
     targets = set()
     applications = set()
     measurements = set()
     experiments = set()
     targ_ctrl = Target.controller(PROJECT_STORAGE)
     app_ctrl = Application.controller(PROJECT_STORAGE)
     meas_ctrl = Measurement.controller(PROJECT_STORAGE)
     expr_ctrl = Experiment.controller(PROJECT_STORAGE)
     for flag in 'impl_experiment', 'impl_project', 'impl_target', 'impl_application', 'impl_measurement':
         for name in getattr(args, flag, []):
             tar = targ_ctrl.one({"name": name})
             app = app_ctrl.one({"name": name})
             mes = meas_ctrl.one({"name": name})
             expr = expr_ctrl.one({"name": name})
             found = {tar, app, mes, expr} - {None}
             if len(found) > 1:
                 self.parser.error(
                     "'%s' is ambiguous. "
                     "Please use a command line flag to specify configuration type."
                     % name)
             elif not found:
                 self.parser.error(
                     "'%s' is not an experiment, target, application, or measurement."
                     % name)
             elif tar:
                 targets.add(tar)
             elif app:
                 applications.add(app)
             elif mes:
                 measurements.add(mes)
             elif expr:
                 experiments.add(expr)
     return targets, applications, measurements, experiments
Exemplo n.º 5
0
 def assertCompiler(self, role, target_name='targ1'):
     from taucmdr.model.target import Target
     targ_ctrl = Target.controller(PROJECT_STORAGE)
     targ = targ_ctrl.one({'name': target_name})
     try:
         return targ.populate(role.keyword)['path']
     except KeyError:
         self.fail("No %s compiler in target '%s'" % (role, target_name))
Exemplo n.º 6
0
 def assertCompiler(self, role, target_name='targ1'):
     from taucmdr.model.target import Target
     targ_ctrl = Target.controller(PROJECT_STORAGE)
     targ = targ_ctrl.one({'name': target_name})
     try:
         return targ.populate(role.keyword)['path']
     except KeyError:
         self.fail("No %s compiler in target '%s'" % (role, target_name))
Exemplo n.º 7
0
 def test_host_family_pgi(self):
     self.reset_project_storage()
     stdout, stderr = self.assertCommandReturnValue(0, create_cmd, ['test_targ', '--compilers', 'PGI'])
     self.assertIn("Added target", stdout)
     self.assertIn("test_targ", stdout)
     self.assertFalse(stderr)
     from taucmdr.cf.storage.levels import PROJECT_STORAGE
     from taucmdr.model.target import Target
     ctrl = Target.controller(PROJECT_STORAGE)
     test_targ = ctrl.one({'name': 'test_targ'})
     path = test_targ.populate(CC.keyword)['path']
     self.assertEqual('pgcc', os.path.basename(path), "Target[CC] is '%s', not 'pgcc'" % path)
Exemplo n.º 8
0
 def test_host_family_pgi(self):
     self.reset_project_storage()
     stdout, stderr = self.assertCommandReturnValue(
         0, create_cmd, ['test_targ', '--compilers', 'PGI'])
     self.assertIn("Added target", stdout)
     self.assertIn("test_targ", stdout)
     self.assertFalse(stderr)
     from taucmdr.cf.storage.levels import PROJECT_STORAGE
     from taucmdr.model.target import Target
     ctrl = Target.controller(PROJECT_STORAGE)
     test_targ = ctrl.one({'name': 'test_targ'})
     path = test_targ.populate(CC.keyword)['path']
     self.assertEqual('pgcc', os.path.basename(path),
                      "Target[CC] is '%s', not 'pgcc'" % path)
Exemplo n.º 9
0
    def _populate_project(self, argv, args):
        def _safe_execute(cmd, argv):
            retval = cmd.main(argv)
            if retval != EXIT_SUCCESS:
                raise InternalError("return code %s: %s %s" % (retval, cmd, ' '.join(argv)))

        # Parse and strip application arguments to avoid ambiguous arguments like '--mpi' in `measurement create`
        application_name = args.application_name
        application_args, unknown = application_create_cmd.parser.parse_known_args([application_name] + argv)
        application_argv = [application_name] + [arg for arg in argv if arg not in unknown]
        _safe_execute(application_create_cmd, application_argv)
        argv = [arg for arg in argv if arg in unknown]
        
        target_name = args.target_name
        _, unknown = target_create_cmd.parser.parse_known_args([target_name] + argv)
        target_argv = [target_name] + [arg for arg in argv if arg not in unknown]
        _safe_execute(target_create_cmd, target_argv)
        
        targ = Target.controller(PROJECT_STORAGE).one({'name': target_name})
        if not targ['binutils_source']:
            self.logger.info("GNU binutils unavailable: disabling sampling and compiler-based instrumentation")
            args.sample = False
            args.compiler_inst = 'never'

        measurement_names = []
        measurement_args = ['--%s=True' % attr for attr in 'cuda', 'mpi', 'opencl', 'shmem' 
                            if getattr(application_args, attr, False)]
        if args.sample:
            trace = args.trace if args.profile == 'none' else 'none'
            _safe_execute(measurement_create_cmd, 
                          ['sample', '--profile', args.profile, '--trace', trace, '--sample=True',
                           '--source-inst=never', '--compiler-inst=never',
                           '--link-only=False'] + measurement_args)
            measurement_names.append('sample')
        if args.profile != 'none':
            _safe_execute(measurement_create_cmd, 
                          ['profile', '--profile', args.profile, '--trace=none', '--sample=False',
                           '--source-inst', args.source_inst, '--compiler-inst', args.compiler_inst, 
                           '--link-only=False'] + measurement_args)
            measurement_names.append('profile')
        if args.trace != 'none':
            _safe_execute(measurement_create_cmd, 
                          ['trace', '--profile=none', '--trace', args.trace, '--sample=False', '--callpath=0', 
                           '--source-inst', args.source_inst, '--compiler-inst', args.compiler_inst, 
                           '--link-only=False'] + measurement_args)
            measurement_names.append('trace')

        select_cmd.main(['--target', target_name, 
                         '--application', application_name, 
                         '--measurement', measurement_names[0]])
Exemplo n.º 10
0
    def main(self, argv):
        from taucmdr.cli.commands.project.list import COMMAND as project_list
        args = self._parse_args(argv)
    
        tar_ctrl = Target.controller(PROJECT_STORAGE)
        app_ctrl = Application.controller(PROJECT_STORAGE)
        meas_ctrl = Measurement.controller(PROJECT_STORAGE)
        proj_ctrl = Project.controller()
    
        project_name = args.name
        project = proj_ctrl.one({'name': project_name})
        if not project:
            self.parser.error("'%s' is not a project name. Type `%s` to see valid names." % 
                              (project_name, project_list.command))
    
        updates = dict(project.element)
        updates['name'] = getattr(args, 'new_name', project_name)
        targets = set(project['targets'])
        applications = set(project['applications'])
        measurements = set(project['measurements'])
        
        added = self._parse_add_args(args, tar_ctrl, app_ctrl, meas_ctrl, targets, applications, measurements)
        removed = self._parse_remove_args(args, tar_ctrl, app_ctrl, meas_ctrl, targets, applications, measurements)
    
        updates['targets'] = list(targets)
        updates['applications'] = list(applications)
        updates['measurements'] = list(measurements)
        
        try:
            force_tau_options = args.force_tau_options
        except AttributeError:
            pass
        else:
            # Unset force_tau_options if it was already set and --force-tau-options=none 
            if updates.pop('force_tau_options', False) and [i.lower().strip() for i in force_tau_options] == ['none']:
                proj_ctrl.unset(['force_tau_options'], {'name': project_name})
                self.logger.info("Removed 'force-tau-options' from project configuration '%s'.", project_name)
            else:
                updates['force_tau_options'] = force_tau_options
                self.logger.info("Added 'force-tau-options' to project configuration '%s'.", project_name)

        proj_ctrl.update(updates, {'name': project_name})
        for model in added:
            self.logger.info("Added %s '%s' to project configuration '%s'.", 
                             model.name.lower(), model[model.key_attribute], project_name)
        for model in removed:
            self.logger.info("Removed %s '%s' from project configuration '%s'.", 
                             model.name.lower(), model[model.key_attribute], project_name)
        return EXIT_SUCCESS
Exemplo n.º 11
0
    def test_host_family_intel(self):
        self.reset_project_storage()
        stdout, stderr = self.assertCommandReturnValue(0, create_cmd, ['test_targ', '--compilers', 'Intel'])
        self.assertIn("Added target", stdout)
        self.assertIn("test_targ", stdout)
        self.assertFalse(stderr)

        from taucmdr.cf.storage.levels import PROJECT_STORAGE
        from taucmdr.model.target import Target
        ctrl = Target.controller(PROJECT_STORAGE)
        test_targ = ctrl.one({'name': 'test_targ'})
        for role, expected in (CC, 'icc'), (CXX, 'icpc'), (FC, 'ifort'):
            path = test_targ.populate(role.keyword)['path']
            self.assertEqual(os.path.basename(path), expected, 
                             "Target[%s] is '%s', not '%s'" % (role, path, expected))
Exemplo n.º 12
0
    def test_host_family_intel(self):
        self.reset_project_storage()
        stdout, stderr = self.assertCommandReturnValue(
            0, create_cmd, ['test_targ', '--compilers', 'Intel'])
        self.assertIn("Added target", stdout)
        self.assertIn("test_targ", stdout)
        self.assertFalse(stderr)

        from taucmdr.cf.storage.levels import PROJECT_STORAGE
        from taucmdr.model.target import Target
        ctrl = Target.controller(PROJECT_STORAGE)
        test_targ = ctrl.one({'name': 'test_targ'})
        for role, expected in (CC, 'icc'), (CXX, 'icpc'), (FC, 'ifort'):
            path = test_targ.populate(role.keyword)['path']
            self.assertEqual(
                os.path.basename(path), expected,
                "Target[%s] is '%s', not '%s'" % (role, path, expected))
Exemplo n.º 13
0
 def main(self, argv):
     args = self._parse_args(argv)
     proj_ctrl = Project.controller()
     proj = proj_ctrl.selected()
     targ = Target.controller(proj_ctrl.storage).one({'name': args.target})
     if targ is None:
         self.parser.error("A target with name %s does not exist." %args.target)
     app = Application.controller(proj_ctrl.storage).one({'name': args.application})
     if app is None:
         self.parser.error("An application with name %s does not exist." %args.application)
     meas = Measurement.controller(proj_ctrl.storage).one({'name': args.measurement})
     if meas is None:
         self.parser.error("A measurement with name %s does not exist." %args.measurement)
     data = {'name': args.name,
             'project': proj.eid,
             'target': targ.eid,
             'application': app.eid,
             'measurement': meas.eid}
     return self._create_record(PROJECT_STORAGE, data)
Exemplo n.º 14
0
Arquivo: edit.py Projeto: HPCL/taucmdr
    def main(self, argv):
        from taucmdr.cli.commands.project.list import COMMAND as project_list
        args = self._parse_args(argv)

        tar_ctrl = Target.controller(PROJECT_STORAGE)
        app_ctrl = Application.controller(PROJECT_STORAGE)
        meas_ctrl = Measurement.controller(PROJECT_STORAGE)
        proj_ctrl = Project.controller()

        project_name = args.name
        project = proj_ctrl.one({'name': project_name})
        if not project:
            self.parser.error(
                "'%s' is not a project name. Type `%s` to see valid names." %
                (project_name, project_list.command))

        updates = dict(project)
        updates['name'] = getattr(args, 'new_name', project_name)
        targets = set(project['targets'])
        applications = set(project['applications'])
        measurements = set(project['measurements'])

        added = self._parse_add_args(args, tar_ctrl, app_ctrl, meas_ctrl,
                                     targets, applications, measurements)
        removed = self._parse_remove_args(args, tar_ctrl, app_ctrl, meas_ctrl,
                                          targets, applications, measurements)

        updates['targets'] = list(targets)
        updates['applications'] = list(applications)
        updates['measurements'] = list(measurements)

        proj_ctrl.update(updates, {'name': project_name})
        for model in added:
            self.logger.info("Added %s '%s' to project configuration '%s'.",
                             model.name.lower(), model[model.key_attribute],
                             project_name)
        for model in removed:
            self.logger.info(
                "Removed %s '%s' from project configuration '%s'.",
                model.name.lower(), model[model.key_attribute], project_name)
        return EXIT_SUCCESS
Exemplo n.º 15
0
 def _parse_implicit(self, args, targets, applications, measurements):
     targ_ctrl = Target.controller(PROJECT_STORAGE)
     app_ctrl = Application.controller(PROJECT_STORAGE)
     meas_ctrl = Measurement.controller(PROJECT_STORAGE)
     for flag in 'impl_targets', 'impl_applications', 'impl_measurements':
         for name in getattr(args, flag, []):
             tar = targ_ctrl.one({"name": name})
             app = app_ctrl.one({"name": name})
             mes = meas_ctrl.one({"name": name})
             tam = set([tar, app, mes]) - set([None])
             if len(tam) > 1:
                 self.parser.error("'%s' is ambiguous.  Please use --target, --application,"
                                   " or --measurement to specify configuration type" % name)
             elif len(tam) == 0:
                 self.parser.error("'%s' is not a target, application, or measurement" % name)
             elif tar:
                 targets.add(tar)
             elif app:
                 applications.add(app)
             elif mes:
                 measurements.add(mes)
Exemplo n.º 16
0
 def main(self, argv):
     args = self._parse_args(argv)
     storage = arguments.parse_storage_flag(args)[0]
     targ_name = args.target_name
     targ = Target.controller(storage).one({'name': targ_name})
     if not targ:
         self.parser.error("No %s-level target named '%s'." % (storage.name, targ_name))
     if args.all:
         args.systems = self._measurement_systems
         args.modifiers = True
     parts = []
     if 'CUPTI' in args.systems:
         parts.extend(self._format_cupti_metrics(targ))
     if 'PAPI_PRESET' in args.systems:
         parts.extend(self._format_papi_metrics(targ, 'PRESET', args.modifiers))
     if 'PAPI_NATIVE' in args.systems:
         parts.extend(self._format_papi_metrics(targ, 'NATIVE', args.modifiers))
     if 'TAU' in args.systems:
         parts.extend(self._format_tau_metrics(targ))
     print '\n'.join(parts)
     return EXIT_SUCCESS
Exemplo n.º 17
0
 def main(self, argv):
     from taucmdr.cli.commands.project.list import COMMAND as project_list
     args = self._parse_args(argv)
 
     tar_ctrl = Target.controller(PROJECT_STORAGE)
     app_ctrl = Application.controller(PROJECT_STORAGE)
     meas_ctrl = Measurement.controller(PROJECT_STORAGE)
     proj_ctrl = Project.controller()
 
     project_name = args.name
     project = proj_ctrl.one({'name': project_name})
     if not project:
         self.parser.error("'%s' is not a project name. Type `%s` to see valid names." % 
                           (project_name, project_list.command))
 
     updates = dict(project)
     updates['name'] = getattr(args, 'new_name', project_name)
     targets = set(project['targets'])
     applications = set(project['applications'])
     measurements = set(project['measurements'])
     
     added = self._parse_add_args(args, tar_ctrl, app_ctrl, meas_ctrl, targets, applications, measurements)
     removed = self._parse_remove_args(args, tar_ctrl, app_ctrl, meas_ctrl, targets, applications, measurements)
 
     updates['targets'] = list(targets)
     updates['applications'] = list(applications)
     updates['measurements'] = list(measurements)
     
     proj_ctrl.update(updates, {'name': project_name})
     for model in added:
         self.logger.info("Added %s '%s' to project configuration '%s'.", 
                          model.name.lower(), model[model.key_attribute], project_name)
     for model in removed:
         self.logger.info("Removed %s '%s' from project configuration '%s'.", 
                          model.name.lower(), model[model.key_attribute], project_name)
     return EXIT_SUCCESS
Exemplo n.º 18
0
def attributes():
    from taucmdr.model.project import Project
    from taucmdr.model.target import Target
    from taucmdr.model.measurement import Measurement
    from taucmdr.cf.platforms import DARWIN, HOST_OS, CRAY_CNL

    def _encourage_except_baseline(lhs, lhs_attr, lhs_value, rhs):
        if isinstance(rhs, Measurement):
            if not rhs['baseline']:
                lhs_name = lhs.name.lower()
                rhs_name = rhs.name.lower()
                LOGGER.warning("%s = %s in %s recommends True in %s", lhs_attr,
                               lhs_value, lhs_name, rhs_name)

    return {
        'projects': {
            'collection': Project,
            'via': 'applications',
            'description': 'projects using this application'
        },
        'name': {
            'primary_key': True,
            'type': 'string',
            'description': 'application configuration name',
            'unique': True
        },
        'openmp': {
            'type': 'boolean',
            'description': 'application uses OpenMP',
            'default': False,
            'argparse': {
                'flags': ('--openmp', )
            },
            'rebuild_required': True
        },
        'pthreads': {
            'type': 'boolean',
            'description': 'application uses pthreads',
            'default': False,
            'argparse': {
                'flags': ('--pthreads', )
            },
            'rebuild_required': True
        },
        'python': {
            'type': 'boolean',
            'description': 'application uses Python',
            'default': False,
            'argparse': {
                'flags': ('--python', )
            },
            'rebuild_required': True
        },
        'tbb': {
            'type': 'boolean',
            'description': 'application uses Thread Building Blocks (TBB)',
            'default': False,
            'argparse': {
                'flags': ('--tbb', )
            },
            'rebuild_required': True
        },
        'mpi': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses MPI',
            'argparse': {
                'flags': ('--mpi', )
            },
            'compat': {
                True: _encourage_except_baseline
            },
            'rebuild_required': True
        },
        'caf': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses Coarray Fortran',
            'argparse': {
                'flags': ('--caf', )
            },
            'compat': {
                True: (_encourage_except_baseline,
                       Measurement.require('source_inst', 'never'))
            },
            'rebuild_required': True
        },
        'cuda': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses NVIDIA CUDA',
            'argparse': {
                'flags': ('--cuda', )
            },
            'compat': {
                True: Target.require('cuda_toolkit')
            },
            'rebuild_required': True
        },
        'opencl': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses OpenCL',
            'argparse': {
                'flags': ('--opencl', )
            },
            'compat': {
                True:
                (Target.require('cuda_toolkit'), _encourage_except_baseline)
            },
            'rebuild_required': True
        },
        'shmem': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses SHMEM',
            'argparse': {
                'flags': ('--shmem', )
            },
            'rebuild_required': True
        },
        'mpc': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses MPC',
            'argparse': {
                'flags': ('--mpc', )
            },
            'rebuild_required': True
        },
        'max_threads': {
            'type': 'integer',
            'description': 'maximum number of threads',
            'argparse': {
                'flags': ('--max-threads', ),
                'metavar': 'threads',
                'nargs': '?',
                'const': 25
            },
            'rebuild_required': True
        },
        'linkage': {
            'type': 'string',
            'default': 'static' if HOST_OS is CRAY_CNL else 'dynamic',
            'description': "application linkage",
            'argparse': {
                'flags': ('--linkage', ),
                'metavar': '<linkage>',
                'choices': ('static', 'dynamic')
            },
            'compat': {
                'static': Target.exclude('host_os', DARWIN)
            },
            'rebuild_required': True
        },
    }
Exemplo n.º 19
0
def attributes():
    from taucmdr.model.project import Project
    from taucmdr.model.target import Target
    from taucmdr.model.measurement import Measurement
    from taucmdr.cf.platforms import DARWIN, HOST_OS, CRAY_CNL
    return {
        'projects': {
            'collection': Project,
            'via': 'applications',
            'description': 'projects using this application'
        },
        'name': {
            'primary_key': True,
            'type': 'string',
            'description': 'application configuration name',
            'unique': True
        },
        'openmp': {
            'type': 'boolean',
            'description': 'application uses OpenMP',
            'default': False,
            'argparse': {'flags': ('--openmp',)},
            'rebuild_required': True
        },
        'pthreads': {
            'type': 'boolean',
            'description': 'application uses pthreads',
            'default': False,
            'argparse': {'flags': ('--pthreads',)},
            'rebuild_required': True
        },
        'tbb': {
            'type': 'boolean',
            'description': 'application uses Thread Building Blocks (TBB)',
            'default': False,
            'argparse': {'flags': ('--tbb',)},
            'rebuild_required': True
        },
        'mpi': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses MPI',
            'argparse': {'flags': ('--mpi',)},
            'compat': {True: Measurement.require('mpi', True)},
            'rebuild_required': True
        },
        'cuda': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses NVIDIA CUDA',
            'argparse': {'flags': ('--cuda',)},
            'compat': {True: Target.require('cuda_toolkit')},
            'rebuild_required': True
        },
        'opencl': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses OpenCL',
            'argparse': {'flags': ('--opencl',)},
            'compat': {True: (Target.require('cuda_toolkit'),
                              Measurement.encourage('opencl', True))},
            'rebuild_required': True
        },
        'shmem': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses SHMEM',
            'argparse': {'flags': ('--shmem',)},
            'rebuild_required': True
        },
        'mpc': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses MPC',
            'argparse': {'flags': ('--mpc',)},
            'rebuild_required': True
        },
        'select_file': {
            'type': 'string',
            'description': 'specify selective instrumentation file',
            'argparse': {'flags': ('--select-file',),
                         'metavar': 'path'},
            'compat': {True: Measurement.exclude('source_inst', 'never')},
            'rebuild_required': True
        },
        'linkage': {
            'type': 'string',
            'default': 'static' if HOST_OS is CRAY_CNL else 'dynamic',
            'description': "application linkage",
            'argparse': {'flags': ('--linkage',),
                         'metavar': '<linkage>',
                         'choices': ('static', 'dynamic')},
            'compat': {'static': Target.exclude('host_os', DARWIN)},
            'rebuild_required': True
        },
    }
Exemplo n.º 20
0
    def _populate_project(self, args):
        # Create default application
        application_name = args.application_name
        cmd_args = Application.filter_arguments(args)
        cmd_args.name = application_name
        cmd_args.openmp = bool(args.openmp)
        if args.openmp is None:
            args.openmp = 'ignore'
        self._safe_execute(application_create_cmd, cmd_args)

        # Create default target
        target_name = args.target_name
        cmd_args = Target.filter_arguments(args)
        cmd_args.name = target_name
        self._safe_execute(target_create_cmd, cmd_args)

        # Target was created so let's see if we can use binutils on this target.
        targ = Target.controller(PROJECT_STORAGE).one({'name': target_name})
        if not targ['binutils_source']:
            self.logger.info("GNU binutils unavailable: disabling sampling and compiler-based instrumentation")
            args.sample = False
            args.compiler_inst = 'never'

        # Create default measurements
        measurements = []
        if args.profile != 'none':
            self._create_measurement(
                'baseline', args, baseline=True, profile='tau', trace='none',
                sample=False, source_inst='never', compiler_inst='never',
                mpi=False, cuda=False, opencl=False, openmp='ignore', shmem=False,
                track_memory_footprint=False, callsite=False, comm_matrix=False,
                heap_usage=False, memory_alloc=False)
            if args.sample:
                measurements.append(self._create_measurement(
                    'sample', args, profile=args.profile, trace='none',
                    sample=True, source_inst='never', compiler_inst='never'))
            if args.source_inst != 'never' or args.compiler_inst != 'never':
                measurements.append(self._create_measurement(
                    'profile', args, profile=args.profile, trace='none',
                    sample=False, source_inst=args.source_inst, compiler_inst=args.compiler_inst))
            if args.source_inst != 'never':
                measurements.append(self._create_measurement(
                    'source-inst', args, profile=args.profile, trace='none',
                    sample=False, source_inst=args.source_inst, compiler_inst='never'))
            if args.compiler_inst != 'never':
                measurements.append(self._create_measurement(
                    'compiler-inst', args, profile=args.profile, trace='none',
                    sample=False, source_inst='never', compiler_inst='always'))
        if args.trace != 'none':
            if args.source_inst != 'never' or args.compiler_inst != 'never':
                measurements.append(self._create_measurement(
                    'trace', args, profile='none', trace=args.trace, callpath=0,
                    sample=False, source_inst=args.source_inst, compiler_inst=args.compiler_inst))
        try:
            measurement_name = measurements[0]
        except IndexError:
            measurement_name = 'baseline'

        # Create default experiment
        select_cmd.main(['--target', target_name,
                         '--application', application_name,
                         '--measurement', measurement_name])
Exemplo n.º 21
0
def attributes():
    """Construct attributes dictionary for the measurement model.
    
    We build the attributes in a function so that classes like ``taucmdr.module.project.Project`` are
    fully initialized and usable in the returned dictionary.
    
    Returns:
        dict: Attributes dictionary.
    """
    from taucmdr.model.project import Project
    from taucmdr.model.target import Target
    from taucmdr.model.application import Application
    from taucmdr.cf.platforms import HOST_OS, DARWIN, IBM_CNK
    from taucmdr.cf.compiler.mpi import MPI_CC, MPI_CXX, MPI_FC
    from taucmdr.cf.compiler.shmem import SHMEM_CC, SHMEM_CXX, SHMEM_FC

    def _merged_profile_compat(lhs, lhs_attr, lhs_value, rhs):
        if isinstance(rhs, Application):
            if not (rhs['mpi'] or rhs['shmem']):
                lhs_name = lhs.name.lower()
                rhs_name = rhs.name.lower()
                raise IncompatibleRecordError(
                    "%s = %s in %s requires either mpi = True or shmem = True in %s"
                    % (lhs_attr, lhs_value, lhs_name, rhs_name))

    def _discourage_callpath(lhs, lhs_attr, lhs_value, rhs):
        if isinstance(rhs, Measurement):
            if rhs.get('callpath', 0) > 0:
                lhs_name = lhs.name.lower()
                rhs_name = rhs.name.lower()
                LOGGER.warning(
                    "%s = %s in %s recommends against callpath > 0 in %s",
                    lhs_attr, lhs_value, lhs_name, rhs_name)

    def _ensure_instrumented(lhs, lhs_attr, lhs_value, rhs):
        if isinstance(rhs, Measurement):
            if rhs.get('source_inst') == 'never' and rhs.get(
                    'compiler_inst') == 'never':
                lhs_name = lhs.name.lower()
                rhs_name = rhs.name.lower()
                raise IncompatibleRecordError(
                    "%s = %s in %s requires source_inst and compiler_inst are not both 'never' in %s"
                    % (lhs_attr, lhs_value, lhs_name, rhs_name))

    return {
        'projects': {
            'collection': Project,
            'via': 'measurements',
            'description': "projects using this measurement"
        },
        'name': {
            'primary_key': True,
            'type': 'string',
            'unique': True,
            'description': "measurement configuration name",
        },
        'baseline': {
            'type': 'boolean',
            'default': False,
            'description':
            "completely disable all instrumentation and measure wall clock time via the OS",
            'argparse': {
                'flags': ('--baseline', ),
                'group': 'instrumentation'
            },
            'compat': {
                True: (Measurement.require('profile', 'tau'),
                       Measurement.require('trace', 'none'))
            }
        },
        'profile': {
            'type': 'string',
            'default': 'tau',
            'description': "generate application profiles",
            'argparse': {
                'flags': ('--profile', ),
                'group': 'output format',
                'metavar': '<format>',
                'nargs': '?',
                'choices': ('tau', 'merged', 'cubex', 'none'),
                'const': 'tau'
            },
            'compat': {
                'cubex': Target.exclude('scorep_source', None),
                'merged': _merged_profile_compat
            },
            'rebuild_required': True
        },
        'trace': {
            'type': 'string',
            'default': 'none',
            'description': "generate application traces",
            'argparse': {
                'flags': ('--trace', ),
                'group': 'output format',
                'metavar': '<format>',
                'nargs': '?',
                'choices': ('slog2', 'otf2', 'none'),
                'const': 'otf2'
            },
            'compat': {
                'otf2': Target.exclude('libotf2_source', None),
                lambda x: x != 'none': _discourage_callpath
            },
            'rebuild_required': True
        },
        'sample': {
            'type': 'boolean',
            'default': HOST_OS not in (DARWIN, IBM_CNK),
            'description':
            "use event-based sampling to gather performance data",
            'argparse': {
                'flags': ('--sample', ),
                'group': 'instrumentation'
            },
            'compat': {
                True:
                (Target.require('binutils_source'),
                 Target.exclude('binutils_source',
                                None), Target.encourage('libunwind_source'),
                 Target.discourage('libunwind_source',
                                   None), Target.exclude('host_os', DARWIN),
                 Measurement.exclude('baseline', True))
            }
        },
        'source_inst': {
            'type': 'string',
            'default': 'never' if HOST_OS is not DARWIN else 'automatic',
            'description':
            "use hooks inserted into the application source code to gather performance data",
            'argparse': {
                'flags': ('--source-inst', ),
                'group': 'instrumentation',
                'metavar': 'mode',
                'nargs': '?',
                'choices': ('automatic', 'manual', 'never'),
                'const': 'automatic'
            },
            'compat': {
                lambda x: x in ('automatic', 'manual'):
                (Target.exclude('pdt_source',
                                None), Measurement.exclude('baseline', True))
            },
            'rebuild_required': True
        },
        'compiler_inst': {
            'type': 'string',
            'default': 'never',
            'description':
            "use compiler-generated callbacks to gather performance data",
            'argparse': {
                'flags': ('--compiler-inst', ),
                'group': 'instrumentation',
                'metavar': 'mode',
                'nargs': '?',
                'choices': ('always', 'fallback', 'never'),
                'const': 'always'
            },
            'compat': {
                lambda x: x in ('always', 'fallback'):
                (Target.require('binutils_source'),
                 Target.exclude('binutils_source',
                                None), Target.require('libunwind_source'),
                 Target.exclude('libunwind_source',
                                None), Target.exclude('host_os', DARWIN),
                 Measurement.exclude('baseline', True))
            },
            'rebuild_required': True
        },
        'mpi': {
            'type': 'boolean',
            'default': False,
            'description':
            'use MPI library wrapper to measure time spent in MPI methods',
            'argparse': {
                'flags': ('--mpi', )
            },
            'compat': {
                True: (Target.require(MPI_CC.keyword),
                       Target.require(MPI_CXX.keyword),
                       Target.require(MPI_FC.keyword),
                       Application.require('mpi', True),
                       Measurement.exclude('baseline', True))
            },
            'rebuild_required': True
        },
        'openmp': {
            'type': 'string',
            'default': 'ignore',
            'description':
            'use specified library to measure time spent in OpenMP directives',
            'argparse': {
                'flags': ('--openmp', ),
                'metavar': 'library',
                'choices': ('ignore', 'opari', 'ompt'),
                'nargs': '?',
                'const': 'ompt'
            },
            'compat': {
                'opari': (Application.require('openmp', True),
                          Measurement.exclude('baseline', True)),
                'ompt': (Application.require('openmp', True),
                         Measurement.exclude('baseline', True))
            },
            'rebuild_required': True
        },
        'cuda': {
            'type': 'boolean',
            'default': False,
            'description': 'measure cuda events via the CUPTI interface',
            'argparse': {
                'flags': ('--cuda', )
            },
            'compat': {
                True: (Target.require('cuda_toolkit'),
                       Application.require('cuda', True),
                       Measurement.exclude('baseline', True))
            },
        },
        'shmem': {
            'type': 'boolean',
            'default': False,
            'description':
            'use SHMEM library wrapper to measure time spent in SHMEM methods',
            'argparse': {
                'flags': ('--shmem', )
            },
            'compat': {
                True: (Target.require(SHMEM_CC.keyword),
                       Target.require(SHMEM_CXX.keyword),
                       Target.require(SHMEM_FC.keyword),
                       Application.require('shmem', True),
                       Measurement.exclude('baseline', True))
            },
            'rebuild_required': True
        },
        'opencl': {
            'type': 'boolean',
            'default': False,
            'description': 'measure OpenCL events',
            'argparse': {
                'flags': ('--opencl', )
            },
            'compat': {
                True: (Target.require('cuda_toolkit'),
                       Application.require('opencl', True),
                       Measurement.exclude('baseline', True))
            },
        },
        'callpath': {
            'type': 'integer',
            'default': 100,
            'description': 'maximum depth for callpath recording',
            'argparse': {
                'flags': ('--callpath', ),
                'group': 'data',
                'metavar': 'depth',
                'nargs': '?',
                'const': 100
            }
        },
        'unwind_depth': {
            'type': 'integer',
            'default': 0,
            'description': 'Record callstack to specified depth',
            'argparse': {
                'flags': ('--unwind-depth', ),
                'group': 'data',
                'metavar': 'depth',
                'nargs': '?',
                'const': 10
            },
            'compat': {
                (lambda unwind: unwind > 0):
                Measurement.exclude('sample', False)
            }
        },
        'io': {
            'type': 'boolean',
            'default': False,
            'description': 'measure time spent in POSIX I/O calls',
            'argparse': {
                'flags': ('--io', )
            },
            'compat': {
                True: Measurement.exclude('baseline', True)
            },
        },
        'heap_usage': {
            'type': 'boolean',
            'default': False,
            'description': 'measure heap memory usage',
            'argparse': {
                'flags': ('--heap-usage', ),
                'group': 'memory'
            },
            'compat': {
                True: Measurement.exclude('baseline', True)
            },
        },
        'system_load': {
            'type': 'boolean',
            'default': False,
            'description': 'measure system load',
            'argparse': {
                'flags': ('--system-load', ),
                'group': 'data'
            },
            'compat': {
                True: Measurement.exclude('baseline', True)
            },
        },
        'memory_alloc': {
            'type': 'boolean',
            'default': False,
            'description':
            'record memory allocation/deallocation events and detect leaks',
            'argparse': {
                'flags': ('--memory-alloc', ),
                'group': 'memory'
            },
            'compat': {
                True: Measurement.exclude('baseline', True)
            },
        },
        'metrics': {
            'type': 'array',
            'default': ['TIME'],
            'description':
            'a space separated list of performance metrics to gather, e.g. TIME PAPI_FP_INS',
            'argparse': {
                'flags': ('--metrics', ),
                'group': 'data',
                'metavar': '<metric>'
            },
            'compat': {
                lambda metrics: bool(
                    len([met for met in metrics if 'PAPI' in met])):
                (Target.require('papi_source'),
                 Target.exclude('papi_source', None)),
                lambda x: x != ['TIME']:
                Measurement.exclude('baseline', True)
            },
            'rebuild_required': True
        },
        'keep_inst_files': {
            'type': 'boolean',
            'default': False,
            'description': "don't remove instrumented files after compilation",
            'argparse': {
                'flags': ('--keep-inst-files', ),
                'group': 'instrumentation'
            },
            'compat': {
                True: Measurement.exclude('source_inst', 'never')
            }
        },
        'reuse_inst_files': {
            'type': 'boolean',
            'default': False,
            'description':
            'reuse and preserve instrumented files after compilation',
            'argparse': {
                'flags': ('--reuse-inst-files', ),
                'group': 'instrumentation'
            },
            'compat': {
                True: Measurement.exclude('source_inst', 'never')
            }
        },
        'comm_matrix': {
            'type': 'boolean',
            'default': False,
            'description': 'record the point-to-point communication matrix',
            'argparse': {
                'flags': ('--comm-matrix', )
            },
            'compat': {
                True: Measurement.exclude('baseline', True)
            },
        },
        'throttle': {
            'type': 'boolean',
            'default': True,
            'description': 'throttle lightweight events to reduce overhead',
            'argparse': {
                'flags': ('--throttle', )
            },
        },
        'throttle_per_call': {
            'type': 'integer',
            'default': 10,
            'description':
            'lightweight event duration threshold in microseconds',
            'argparse': {
                'flags': ('--throttle-per-call', ),
                'metavar': 'us',
                'nargs': '?',
                'const': 10
            },
        },
        'throttle_num_calls': {
            'type': 'integer',
            'default': 100000,
            'description': 'lightweight event call count threshold',
            'argparse': {
                'flags': ('--throttle-num-calls', ),
                'metavar': 'count',
                'nargs': '?',
                'const': 100000
            },
        },
        'sampling_period': {
            'type': 'integer',
            'default': 5000,
            'description': 'default sampling period in microseconds',
            'argparse': {
                'flags': ('--sampling-period', ),
                'metavar': 'us',
                'nargs': '?',
                'const': 5000
            },
            'compat': {
                True: (Measurement.require('sample', True))
            },
        },
        'track_memory_footprint': {
            'type': 'boolean',
            'default': False,
            'description': 'track memory footprint',
            'argparse': {
                'flags': ('--track-memory-footprint', ),
                'group': 'memory'
            },
            'compat': {
                True: Measurement.exclude('baseline', True)
            },
        },
        'metadata_merge': {
            'type': 'boolean',
            'default': True,
            'description': 'merge metadata of TAU profiles',
            'argparse': {
                'flags': ('--metadata-merge', )
            },
        },
        'callsite': {
            'type': 'boolean',
            'default': False,
            'description': 'record event callsites',
            'argparse': {
                'flags': ('--callsite', )
            },
            'compat': {
                True:
                (Target.require('binutils_source'),
                 Target.exclude('binutils_source',
                                None), Target.encourage('libunwind_source'),
                 Target.discourage('libunwind_source',
                                   None), Target.exclude('host_os', DARWIN),
                 Measurement.exclude('baseline', True))
            }
        },
        'select_file': {
            'type': 'string',
            'description': 'specify selective instrumentation file',
            'argparse': {
                'flags': ('--select-file', ),
                'metavar': 'path'
            },
            'compat': {
                bool: (_ensure_instrumented,
                       Application.discourage('linkage', 'static'),
                       Measurement.discourage('throttle', True))
            },
            'rebuild_required': True
        },
        'update_nightly': {
            'type': 'boolean',
            'default': False,
            'description': 'Download newest TAU nightly',
            'argparse': {
                'flags': ('--update-nightly', )
            },
            'compat': {
                bool: (Target.require('tau_source', 'nightly'))
            },
        },
        'ptts': {
            'type': 'boolean',
            'default': False,
            'description': 'enable support for PTTS',
            'argparse': {
                'flags': ('--ptts', )
            },
        },
        'ptts_post': {
            'type': 'boolean',
            'default': False,
            'description':
            'skip application sampling and post-process existing PTTS sample files',
            'argparse': {
                'flags': ('--ptts-post', )
            },
            'compat': {
                bool: (Measurement.require('ptts', True))
            },
        },
        'ptts_sample_flags': {
            'type': 'string',
            'default': '',  #None, 
            'description': 'flags to pass to PTTS sample_ts command',
            'argparse': {
                'flags': ('--ptts-sample-flags', ),
                'metavar': 'sample_flags'
            },
            'compat': {
                bool: (Measurement.require('ptts', True))
            },
        },
        'ptts_restart': {
            'type': 'boolean',
            'default': False,
            'description':
            'enable restart support within PTTS, allowing application to continue running and be reinstrumented after stop',
            'argparse': {
                'flags': ('--ptts-restart', )
            },
            'compat': {
                bool: (Measurement.require('ptts', True))
            },
        },
        'ptts_start': {
            'type': 'string',
            'default': '',  #None,
            'description': 'address at which to start a PTTS sampling region',
            'argparse': {
                'flags': ('--ptts-start', )
            },
            'compat': {
                bool: (Measurement.require('ptts', True))
            },
        },
        'ptts_stop': {
            'type': 'string',
            'default': '',  #None,
            'description': 'address at which to stop a PTTS sampling region',
            'argparse': {
                'flags': ('--ptts-stop', )
            },
            'compat': {
                bool: (Measurement.require('ptts', True))
            },
        },
        'ptts_report_flags': {
            'type': 'string',
            'default': '',  #None,
            'description': 'flags to pass to PTTS report_ts command',
            'argparse': {
                'flags': ('--ptts-report-flags', )
            },
            'compat': {
                bool: (Measurement.require('ptts', True))
            },
        },
        'extra_tau_options': {
            'type': 'string',
            'description':
            'forcibly add to the TAU_OPTIONS environment variable (not recommended)',
            'rebuild_on_change': True,
            'argparse': {
                'flags': ('--extra-tau-options', ),
                'nargs': '+',
                'metavar': '<option>'
            },
            'compat': {
                bool: (Measurement.discourage('extra_tau_options'),
                       Measurement.exclude('baseline', True))
            }
        },
        'mpit': {
            'type': 'boolean',
            'default': False,
            'description': 'MPI-T profiling interface',
            'argparse': {
                'flags': ('--mpit', )
            },
        },
        'force_tau_options': {
            'type': 'array',
            'description':
            "forcibly set the TAU_OPTIONS environment variable (not recommended)",
            'rebuild_on_change': True,
            'argparse': {
                'flags': ('--force-tau-options', ),
                'nargs': '+',
                'metavar': '<option>'
            },
            'compat': {
                bool: (Measurement.discourage('force_tau_options'),
                       Measurement.exclude('extra_tau_options'),
                       Measurement.exclude('baseline', True))
            }
        },
        'tag': {
            'type': 'string',
            'description': "Narrow search for tags",
            'default': '',  #None,
            'argparse': {
                'flags': ('--tag', ),
                'nargs': '+',
                'metavar': '<tags>'
            }
        },
        'extra_tau_options': {
            'type': 'array',
            'description':
            "append extra options to TAU_OPTIONS environment variable (not recommended)",
            'rebuild_on_change': True,
            'argparse': {
                'flags': ('--extra-tau-options', ),
                'nargs': '+',
                'metavar': '<option>'
            },
            'compat': {
                bool: (Measurement.discourage('extra_tau_options'),
                       Measurement.exclude('force_tau_options'),
                       Measurement.exclude('baseline', True))
            }
        }
    }
Exemplo n.º 22
0
def attributes():
    from taucmdr.model.project import Project
    from taucmdr.model.target import Target
    from taucmdr.model.measurement import Measurement
    from taucmdr.cf.platforms import DARWIN, HOST_OS, CRAY_CNL
    return {
        'projects': {
            'collection': Project,
            'via': 'applications',
            'description': 'projects using this application'
        },
        'name': {
            'primary_key': True,
            'type': 'string',
            'description': 'application configuration name',
            'unique': True
        },
        'openmp': {
            'type': 'boolean',
            'description': 'application uses OpenMP',
            'default': False,
            'argparse': {
                'flags': ('--openmp', )
            },
            'rebuild_required': True
        },
        'pthreads': {
            'type': 'boolean',
            'description': 'application uses pthreads',
            'default': False,
            'argparse': {
                'flags': ('--pthreads', )
            },
            'rebuild_required': True
        },
        'tbb': {
            'type': 'boolean',
            'description': 'application uses Thread Building Blocks (TBB)',
            'default': False,
            'argparse': {
                'flags': ('--tbb', )
            },
            'rebuild_required': True
        },
        'mpi': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses MPI',
            'argparse': {
                'flags': ('--mpi', )
            },
            'compat': {
                True: Measurement.encourage('mpi', True)
            },
            'rebuild_required': True
        },
        'cuda': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses NVIDIA CUDA',
            'argparse': {
                'flags': ('--cuda', )
            },
            'compat': {
                True: Target.require('cuda_toolkit')
            },
            'rebuild_required': True
        },
        'opencl': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses OpenCL',
            'argparse': {
                'flags': ('--opencl', )
            },
            'compat': {
                True: (Target.require('cuda_toolkit'),
                       Measurement.encourage('opencl', True))
            },
            'rebuild_required': True
        },
        'shmem': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses SHMEM',
            'argparse': {
                'flags': ('--shmem', )
            },
            'rebuild_required': True
        },
        'mpc': {
            'type': 'boolean',
            'default': False,
            'description': 'application uses MPC',
            'argparse': {
                'flags': ('--mpc', )
            },
            'rebuild_required': True
        },
        'select_file': {
            'type': 'string',
            'description': 'specify selective instrumentation file',
            'argparse': {
                'flags': ('--select-file', ),
                'metavar': 'path'
            },
            'compat': {
                bool: (Measurement.exclude('source_inst', 'never'),
                       Application.discourage('linkage', 'static'))
            },
            'rebuild_required': True
        },
        'linkage': {
            'type': 'string',
            'default': 'static' if HOST_OS is CRAY_CNL else 'dynamic',
            'description': "application linkage",
            'argparse': {
                'flags': ('--linkage', ),
                'metavar': '<linkage>',
                'choices': ('static', 'dynamic')
            },
            'compat': {
                'static': Target.exclude('host_os', DARWIN)
            },
            'rebuild_required': True
        },
    }
Exemplo n.º 23
0
def attributes():
    """Construct attributes dictionary for the measurement model.
    
    We build the attributes in a function so that classes like ``taucmdr.module.project.Project`` are
    fully initialized and usable in the returned dictionary.
    
    Returns:
        dict: Attributes dictionary.
    """
    from taucmdr.model.project import Project
    from taucmdr.model.target import Target
    from taucmdr.model.application import Application
    from taucmdr.cf.platforms import HOST_OS, DARWIN, IBM_CNK
    from taucmdr.cf.compiler.mpi import MPI_CC, MPI_CXX, MPI_FC
    from taucmdr.cf.compiler.shmem import SHMEM_CC, SHMEM_CXX, SHMEM_FC
    
    def _merged_profile_compat(lhs, lhs_attr, lhs_value, rhs):
        if isinstance(rhs, Application):
            if not (rhs['mpi'] or rhs['shmem']):
                lhs_name = lhs.name.lower()
                rhs_name = rhs.name.lower()
                raise IncompatibleRecordError("%s = %s in %s requires either mpi = True or shmem = True in %s" % 
                                              (lhs_attr, lhs_value, lhs_name, rhs_name))


    def _discourage_callpath(lhs, lhs_attr, lhs_value, rhs):
        if isinstance(rhs, Measurement):
            if rhs.get('callpath', 0) > 0:
                lhs_name = lhs.name.lower()
                rhs_name = rhs.name.lower()
                LOGGER.warning("%s = %s in %s recommends against callpath > 0 in %s",
                               lhs_attr, lhs_value, lhs_name, rhs_name)


    return {
        'projects': {
            'collection': Project,
            'via': 'measurements',
            'description': "projects using this measurement"
        },
        'name': {
            'primary_key': True,
            'type': 'string',
            'unique': True,
            'description': "measurement configuration name",
        },
        'profile': {
            'type': 'string',
            'default': 'tau',
            'description': "generate application profiles",
            'argparse': {'flags': ('--profile',),
                         'group': 'output format',
                         'metavar': '<format>',
                         'nargs': '?',
                         'choices': ('tau', 'merged', 'cubex', 'none'),
                         'const': 'tau'},
            'compat': {'cubex': (Target.exclude('scorep_source', None),
                                 Application.require('mpi', True),
                                 Measurement.require('mpi', True)),
                       'merged': _merged_profile_compat},
        },
        'trace': {
            'type': 'string',
            'default': 'none',
            'description': "generate application traces",
            'argparse': {'flags': ('--trace',),
                         'group': 'output format',
                         'metavar': '<format>',
                         'nargs': '?',
                         'choices':('slog2', 'otf2', 'none'),
                         'const': 'otf2'},
            'compat': {'otf2': Target.exclude('libotf2_source', None),
                       lambda x: x != 'none': _discourage_callpath}
        },
        'sample': {
            'type': 'boolean',
            'default': HOST_OS not in (DARWIN, IBM_CNK),
            'description': "use event-based sampling to gather performance data",
            'argparse': {'flags': ('--sample',),
                         'group': 'instrumentation'},
            'compat': {True: (Target.require('binutils_source'),
                              Target.exclude('binutils_source', None),
                              Target.encourage('libunwind_source'),
                              Target.discourage('libunwind_source', None),
                              Target.exclude('host_os', DARWIN))}
        },
        'source_inst': {
            'type': 'string',
            'default': 'never' if HOST_OS is not DARWIN else 'automatic',
            'description': "use hooks inserted into the application source code to gather performance data",
            'argparse': {'flags': ('--source-inst',),
                         'group': 'instrumentation',
                         'metavar': 'mode',
                         'nargs': '?',
                         'choices': ('automatic', 'manual', 'never'),
                         'const': 'automatic'},
            'compat': {'automatic': Target.exclude('pdt_source', None)},
            'rebuild_required': True
        },
        'compiler_inst': {
            'type': 'string',
            'default': 'never',
            'description': "use compiler-generated callbacks to gather performance data",
            'argparse': {'flags': ('--compiler-inst',),
                         'group': 'instrumentation',
                         'metavar': 'mode',
                         'nargs': '?',
                         'choices': ('always', 'fallback', 'never'),
                         'const': 'always'},
            'compat': {lambda x: x in ('always', 'fallback'):
                       (Target.require('binutils_source'),
                        Target.exclude('binutils_source', None),
                        Target.require('libunwind_source'),
                        Target.exclude('libunwind_source', None),
                        Target.exclude('host_os', DARWIN))},
            'rebuild_required': True
        },
        'link_only': {
            'type': 'boolean',
            'default': False,
            'description': "don't instrument, only link the TAU library to the application",
            'argparse': {'flags': ('--link-only',),
                         'group': 'instrumentation'},
            'rebuild_required': True
        },
        'mpi': {
            'type': 'boolean',
            'default': False,
            'description': 'use MPI library wrapper to measure time spent in MPI methods',
            'argparse': {'flags': ('--mpi',)},
            'compat': {True:
                       (Target.require(MPI_CC.keyword),
                        Target.require(MPI_CXX.keyword),
                        Target.require(MPI_FC.keyword))},
            'rebuild_required': True
        },
        'openmp': {
            'type': 'string',
            'default': 'ignore',
            'description': 'use specified library to measure time spent in OpenMP directives',
            'argparse': {'flags': ('--openmp',),
                         'metavar': 'library',
                         'choices': ('ignore', 'opari', 'ompt')},
            'compat': {'opari':
                       (Application.require('openmp', True),
                        Measurement.discourage('source_inst', 'never')),
                       'ompt': Application.require('openmp', True)},
            'rebuild_required': True
        },
        'cuda': {
            'type': 'boolean',
            'default': False,
            'description': 'measure cuda events via the CUPTI interface',
            'argparse': {'flags': ('--cuda',)},
            'compat': {True: Target.require('cuda_toolkit')},
        },
        'shmem': {
            'type': 'boolean',
            'default': False,
            'description': 'use SHMEM library wrapper to measure time spent in SHMEM methods',
            'argparse': {'flags': ('--shmem',)},
            'compat': {True:
                       (Target.require(SHMEM_CC.keyword),
                        Target.require(SHMEM_CXX.keyword),
                        Target.require(SHMEM_FC.keyword))},
            'rebuild_required': True
        },
        'opencl': {
            'type': 'boolean',
            'default': False,
            'description': 'measure OpenCL events',
            'argparse': {'flags': ('--opencl',)},
            'compat': {True: (Target.require('cuda_toolkit'),
                              Application.require('opencl'))},
        },
        'callpath': {
            'type': 'integer',
            'default': 100,
            'description': 'maximum depth for callpath recording',
            'argparse': {'flags': ('--callpath',),
                         'group': 'data',
                         'metavar': 'depth',
                         'nargs': '?',
                         'const': 100}
        },
        'io': {
            'type': 'boolean',
            'default': False,
            'description': 'measure time spent in POSIX I/O calls',
            'argparse': {'flags': ('--io',)},
        },
        'heap_usage': {
            'type': 'boolean',
            'default': False,
            'description': 'measure heap memory usage',
            'argparse': {'flags': ('--heap-usage',),
                         'group': 'memory'},
        },
        'memory_alloc': {
            'type': 'boolean',
            'default': False,
            'description': 'record memory allocation/deallocation events and detect leaks',
            'argparse': {'flags': ('--memory-alloc',),
                         'group': 'memory'},
        },
        'metrics': {
            'type': 'array',
            'default': ['TIME'],
            'description': 'performance metrics to gather, e.g. TIME, PAPI_FP_INS',
            'argparse': {'flags': ('--metrics',),
                         'group': 'data',
                         'metavar': '<metric>'},
            'compat': {lambda metrics: bool(len([met for met in metrics if 'PAPI' in met])):
                       (Target.require('papi_source'), 
                        Target.exclude('papi_source', None))},
            'rebuild_required': True
        },
        'keep_inst_files': {
            'type': 'boolean',
            'default': False,
            'description': "don't remove instrumented files after compilation",
            'argparse': {'flags': ('--keep-inst-files',),
                         'group': 'instrumentation'},
            'compat': {True: Measurement.exclude('source_inst', 'never')}
        },
        'reuse_inst_files': {
            'type': 'boolean',
            'default': False,
            'description': 'reuse and preserve instrumented files after compilation',
            'argparse': {'flags': ('--reuse-inst-files',),
                         'group': 'instrumentation'},
            'compat': {True: Measurement.exclude('source_inst', 'never')}
        },
        'comm_matrix': {
            'type': 'boolean',
            'default': False,
            'description': 'record the point-to-point communication matrix',
            'argparse': {'flags': ('--comm-matrix',)}
        },
        'throttle': {
            'type': 'boolean',
            'default': True,
            'description': 'throttle lightweight events to reduce overhead',
            'argparse': {'flags': ('--throttle',)},
        },
        'throttle_per_call': {
            'type': 'integer',
            'default': 10,
            'description': 'lightweight event duration threshold in microseconds',
            'argparse': {'flags': ('--throttle-per-call',),
                         'metavar': 'us',
                         'nargs': '?',
                         'const': 10},
        },
        'throttle_num_calls': {
            'type': 'integer',
            'default': 100000,
            'description': 'lightweight event call count threshold',
            'argparse': {'flags': ('--throttle-num-calls',),
                         'metavar': 'count',
                         'nargs': '?',
                         'const': 100000},
        },
        'metadata_merge': {
            'type': 'boolean',
            'default': True,
            'description': 'merge metadata of TAU profiles',
            'argparse': {'flags': ('--metadata-merge',)},
        },
        'callsite': {
            'type': 'boolean',
            'default': False,
            'description': 'record event callsites',
            'argparse': {'flags': ('--callsite',)},
            'compat': {True: (Target.require('binutils_source'),
                              Target.exclude('binutils_source', None),
                              Target.encourage('libunwind_source'),
                              Target.discourage('libunwind_source', None),
                              Target.exclude('host_os', DARWIN))}
        },
    }