示例#1
0
    def __call__(self,
                 command,
                 *args,
                 project=None,
                 rerun_on_error=True,
                 **kwargs):
        if project:
            self.project = project

        original_command = command[args]
        new_command = command["-Qunused-arguments"]
        new_command = new_command[args]
        new_command = new_command[self.project.cflags]
        new_command = new_command[self.project.ldflags]

        with track_execution(new_command, self.project, self.experiment,
                             **kwargs) as run:
            run_info = run()
            if self.config:
                LOG.info(
                    yaml.dump(self.config,
                              width=40,
                              indent=4,
                              default_flow_style=False))
                persist_config(run_info.db_run, run_info.session, self.config)

            if run_info.has_failed:
                with track_execution(original_command, self.project,
                                     self.experiment, **kwargs) as run:
                    LOG.warning("Fallback to: %s", str(original_command))
                    run_info = run()

        res = self.call_next(new_command, *args, **kwargs)
        res.append(run_info)
        return res
示例#2
0
    def __call__(self, cc, *args, project=None, **kwargs):
        if project:
            self.project = project

        original_command = cc[args]
        clang = cc["-Qunused-arguments"]
        clang = clang[args]
        clang = clang[project.cflags]
        clang = clang[project.ldflags]
        clang = clang["-mllvm", "-stats"]

        run_config = self.config
        session = schema.Session()
        with u_run.track_execution(clang, self.project, self.experiment) as _run:
            run_info = _run()
            if run_config is not None:
                db.persist_config(run_info.db_run, session, run_config)

            if not run_info.has_failed:
                stats = []
                cls = ExtractCompileStats
                for stat in cls.get_compilestats(run_info.stderr):
                    compile_s = CompileStat()
                    compile_s.name = stat["desc"].rstrip()
                    compile_s.component = stat["component"].rstrip()
                    compile_s.value = stat["value"]
                    stats.append(compile_s)

                components = settings.CFG["cs"]["components"].value
                names = settings.CFG["cs"]["names"].value

                stats = [s for s in stats if str(s.component) in components] \
                    if components is not None else stats
                stats = [s for s in stats if str(s.name) in names] \
                    if names is not None else stats

                if stats:
                    for stat in stats:
                        LOG.info(" [%s] %s = %s", stat.component, stat.name,
                                 stat.value)
                    db.persist_compilestats(run_info.db_run, run_info.session,
                                            stats)
                else:
                    LOG.info("No compilestats left, after filtering.")
                    LOG.warning("  Components: %s", components)
                    LOG.warning("  Names:      %s", names)
            else:
                with u_run.track_execution(original_command, self.project,
                                         self.experiment, **kwargs) as _run:
                    LOG.warning("Fallback to: %s", str(original_command))
                    run_info = _run()

        ret = self.call_next(cc, *args, **kwargs)
        ret.append(run_info)
        session.commit()
        return ret
示例#3
0
def run_raw(project, experiment, config, run_f, args, **kwargs):
    """
    Run the given binary wrapped with nothing.

    Args:
        project: The benchbuild.project.
        experiment: The benchbuild.experiment.
        config: The benchbuild.settings.config.
        run_f: The file we want to execute.
        args: List of arguments that should be passed to the wrapped binary.
        **kwargs: Dictionary with our keyword args. We support the following
            entries:

            project_name: The real name of our project. This might not
                be the same as the configured project name, if we got wrapped
                with ::benchbuild.project.wrap_dynamic
            has_stdin: Signals whether we should take care of stdin.
    """
    from benchbuild.utils.run import track_execution
    from benchbuild.utils.run import handle_stdin
    from benchbuild.settings import CFG

    CFG.update(config)
    project.name = kwargs.get("project_name", project.name)

    run_cmd = local[run_f]
    run_cmd = handle_stdin(run_cmd[args], kwargs)
    with track_execution(run_cmd, project, experiment) as run:
        run()
示例#4
0
def run_with_perf(project, experiment, config, jobs, run_f, args, **kwargs):
    """
    Run the given binary wrapped with time.

    Args:
        project: The benchbuild.project.
        experiment: The benchbuild.experiment.
        config: The benchbuild.settings.config.
        jobs: Number of cores we should use for this exection.
        run_f: The file we want to execute.
        args: List of arguments that should be passed to the wrapped binary.
        **kwargs: Dictionary with our keyword args. We support the following
            entries:

            project_name: The real name of our project. This might not
                be the same as the configured project name, if we got wrapped
                with ::benchbuild.project.wrap_dynamic
            has_stdin: Signals whether we should take care of stdin.
    """
    project.name = kwargs.get("project_name", project.name)
    run_cmd = local[run_f]
    run_cmd = run_cmd[args]
    run_cmd = perf["record", "-q", "-F", 6249, "-g", run_cmd]

    with local.env(OMP_NUM_THREADS=str(jobs)):
        with run.track_execution(run_cmd, project, experiment) as command:
            command(retcode=None)
示例#5
0
        def _track_compilestats(project, experiment, config, clang, **kwargs):
            """Compile the project and track the compilestats."""
            from benchbuild.settings import CFG
            from benchbuild.utils.run import handle_stdin

            CFG.update(config)
            clang = handle_stdin(clang["-mllvm", "-polli-collect-modules"],
                                 kwargs)
            with track_execution(clang, project, experiment) as run:
                run()
示例#6
0
    def __call__(self,
                 command: BoundCommand,
                 *args: tp.Any,
                 project: Project = None,
                 rerun_on_error: bool = True,
                 **kwargs: tp.Any) -> tp.List[run.RunInfo]:

        res: tp.List[run.RunInfo] = self.call_next(command, *args, **kwargs)

        for arg in args:
            if arg.endswith(".cpp"):
                src_file = arg
                break

        fake_file_name = src_file.replace(".cpp", "_fake.ll")

        clang_stage_1 = command[self.extra_ldflags, "-Qunused-arguments",
                                "-fvara-handleRM=High", "-S", "-emit-llvm",
                                "-o", fake_file_name, src_file]
        with run.track_execution(clang_stage_1, self.project,
                                 self.experiment) as _run:
            res.append(_run())

        opt = local["opt"]["-vara-HD", "-vara-trace", "-vara-trace-RTy=High",
                           f"-vara-trace-MTy={self.marker_type}", "-S", "-o",
                           "traced.ll", fake_file_name]
        with run.track_execution(opt, self.project, self.experiment) as _run:
            res.append(_run())

        llc = local["llc"]["-filetype=obj", "-o", "traced.o", "traced.ll"]
        with run.track_execution(llc, self.project, self.experiment) as _run:
            res.append(_run())

        clang_stage_2 = command["-O2", "traced.o", self.extra_ldflags,
                                "-lSTrace", "-o",
                                src_file.replace(".cpp", "_traced")]
        with run.track_execution(clang_stage_2, self.project,
                                 self.experiment) as _run:
            res.append(_run())

        return res
示例#7
0
def run_without_recompile(project, experiment, config, jobs, run_f, args,
                          **kwargs):
    """
    Run the given binary wrapped with time.

    Args:
        project: The benchbuild.project.
        experiment: The benchbuild.experiment.
        config: The benchbuild.settings.config.
        jobs: Number of cores we should use for this exection.
        run_f: The file we want to execute.
        args: List of arguments that should be passed to the wrapped binary.
        **kwargs: Dictionary with our keyword args. We support the following
            entries:

            project_name: The real name of our project. This might not
                be the same as the configured project name, if we got wrapped
                with ::benchbuild.project.wrap_dynamic
            has_stdin: Signals whether we should take care of stdin.
    """
    from benchbuild.utils.run import track_execution, fetch_time_output
    from benchbuild.settings import CFG
    from benchbuild.utils.db import persist_time, persist_config

    CFG.update(config)
    project.name = kwargs.get("project_name", project.name)
    timing_tag = "BB-JIT: "

    may_wrap = kwargs.get("may_wrap", True)

    run_cmd = local[run_f]
    run_cmd = run_cmd[args]
    if may_wrap:
        run_cmd = time["-f", timing_tag + "%U-%S-%e", run_cmd]

    with local.env(OMP_NUM_THREADS=str(jobs),
                   POLLI_LOG_FILE=CFG["slurm"]["extra_log"].value()):
        with track_execution(run_cmd, project, experiment) as run:
            ri = run()

        if may_wrap:
            timings = fetch_time_output(timing_tag,
                                        timing_tag + "{:g}-{:g}-{:g}",
                                        ri.stderr.split("\n"))
            if timings:
                persist_time(ri.db_run, ri.session, timings)
    persist_config(
        ri.db_run, ri.session, {
            "cores": str(jobs - 1),
            "cores-config": str(jobs),
            "recompilation": "disabled"
        })
    return ri
示例#8
0
def run_with_time(project, experiment, config, jobs, run_f, args, **kwargs):
    """
    Run the given binary wrapped with time.

    Args:
        project: The benchbuild project that has called us.
        experiment: The benchbuild experiment which we operate under.
        config: The benchbuild configuration we are running with.
        jobs: The number of cores we are allowed to use. This may differ
            from the actual amount of available cores, obey it.
            We should enforce this from the outside. However, at the moment we
            do not do this.
        run_f: The file we want to execute.
        args: List of arguments that should be passed to the wrapped binary.
        **kwargs: Dictionary with our keyword args. We support the following
            entries:

            project_name: The real name of our project. This might not
                be the same as the configured project name, if we got wrapped
                with ::benchbuild.project.wrap_dynamic
            has_stdin: Signals whether we should take care of stdin.
            may_wrap:
                Project may signal that it they are not suitable for
                wrapping. Usually because they scan/parse the output, which
                may interfere with the output of the wrapper binary.
    """
    CFG.update(config)
    project.name = kwargs.get("project_name", project.name)
    timing_tag = "BB-TIME: "

    may_wrap = kwargs.get("may_wrap", True)

    run_cmd = local[run_f]
    run_cmd = run_cmd[args]
    if may_wrap:
        run_cmd = time["-f", timing_tag + "%U-%S-%e", run_cmd]

    def handle_timing_info(ri):
        if may_wrap:
            timings = fetch_time_output(timing_tag,
                                        timing_tag + "{:g}-{:g}-{:g}",
                                        ri.stderr.split("\n"))
            if timings:
                persist_time(ri.db_run, ri.session, timings)
            else:
                logging.warn("No timing information found.")
        return ri

    with track_execution(run_cmd, project, experiment, **kwargs) as run:
        ri = handle_timing_info(run())
    persist_config(ri.db_run, ri.session, {"cores": str(jobs)})
    return ri
示例#9
0
    def __call__(self,
                 command,
                 *args,
                 project=None,
                 rerun_on_error=True,
                 **kwargs):
        if project:
            self.project = project

        original_command = command[args]
        new_command = command["-Qunused-arguments"]
        new_command = new_command[args]
        new_command = new_command[self.project.cflags]
        new_command = new_command[self.project.ldflags]

        with run.track_execution(new_command, self.project, self.experiment,
                                 **kwargs) as _run:
            run_info = _run()
            if self.config:
                LOG.info(
                    yaml.dump(
                        self.config,
                        width=40,
                        indent=4,
                        default_flow_style=False))
                db.persist_config(run_info.db_run, run_info.session,
                                  self.config)

            if run_info.has_failed:
                with run.track_execution(original_command, self.project,
                                         self.experiment, **kwargs) as _run:
                    LOG.warning("Fallback to: %s", str(original_command))
                    run_info = _run()

        res = self.call_next(new_command, *args, **kwargs)
        res.append(run_info)
        return res
示例#10
0
def run_with_likwid(project, experiment, config, jobs, run_f, args, **kwargs):
    """
    Run the given file wrapped by likwid.

    Args:
        project: The benchbuild.project.
        experiment: The benchbuild.experiment.
        config: The benchbuild.settings.config.
        jobs: Number of cores we should use for this exection.
        run_f: The file we want to execute.
        args: List of arguments that should be passed to the wrapped binary.
        **kwargs: Dictionary with our keyword args. We support the following
            entries:

            project_name: The real name of our project. This might not
                be the same as the configured project name, if we got wrapped
                with ::benchbuild.project.wrap_dynamic
            has_stdin: Signals whether we should take care of stdin.
    """
    from benchbuild.settings import CFG
    from benchbuild.utils.run import track_execution, handle_stdin
    from benchbuild.utils.db import persist_likwid, persist_config
    from benchbuild.likwid import get_likwid_perfctr

    CFG.update(config)
    project.name = kwargs.get("project_name", project.name)
    likwid_f = project.name + ".txt"

    for group in ["CLOCK"]:
        likwid_path = path.join(CFG["likwiddir"], "bin")
        likwid_perfctr = local[path.join(likwid_path, "likwid-perfctr")]
        run_cmd = \
            likwid_perfctr["-O", "-o", likwid_f, "-m",
                           "-C", "0-{0:d}".format(jobs),
                           "-g", group, run_f]
        run_cmd = handle_stdin(run_cmd[args], kwargs)

        with local.env(POLLI_ENABLE_LIKWID=1):
            with track_execution(run_cmd, project, experiment) as run:
                ri = run()

        likwid_measurement = get_likwid_perfctr(likwid_f)
        persist_likwid(run, ri.session, likwid_measurement)
        persist_config(run, ri.session, {
            "cores": str(jobs),
            "likwid.group": group
        })
        rm("-f", likwid_f)
示例#11
0
def run_with_perf(project, experiment, config, jobs, run_f, args, **kwargs):
    """
    Run the given binary wrapped with time.

    Args:
        project: The benchbuild.project.
        experiment: The benchbuild.experiment.
        config: The benchbuild.settings.config.
        jobs: Number of cores we should use for this exection.
        run_f: The file we want to execute.
        args: List of arguments that should be passed to the wrapped binary.
        **kwargs: Dictionary with our keyword args. We support the following
            entries:

            project_name: The real name of our project. This might not
                be the same as the configured project name, if we got wrapped
                with ::benchbuild.project.wrap_dynamic
            has_stdin: Signals whether we should take care of stdin.
    """
    from benchbuild.settings import CFG
    from benchbuild.utils.run import track_execution, handle_stdin
    from benchbuild.utils.db import persist_perf, persist_config
    from benchbuild.utils.cmd import perf

    CFG.update(config)
    project.name = kwargs.get("project_name", project.name)
    run_cmd = local[run_f]
    run_cmd = handle_stdin(run_cmd[args], kwargs)
    run_cmd = perf["record", "-q", "-F", 6249, "-g", run_cmd]

    with local.env(OMP_NUM_THREADS=str(jobs)):
        with track_execution(run_cmd, project, experiment) as run:
            ri = run(retcode=None)

        fg_path = path.join(CFG["src_dir"], "extern/FlameGraph")
        if path.exists(fg_path):
            sc_perf = local[path.join(fg_path, "stackcollapse-perf.pl")]
            flamegraph = local[path.join(fg_path, "flamegraph.pl")]

            fold_cmd = ((perf["script"] | sc_perf) > run_f + ".folded")
            graph_cmd = (flamegraph[run_f + ".folded"] > run_f + ".svg")

            fold_cmd()
            graph_cmd()
            persist_perf(ri.db_run, ri.session, run_f + ".svg")
            persist_config(ri.db_run, ri.session, {"cores": str(jobs)})
示例#12
0
def collect_compilestats(project, experiment, clang, **kwargs):
    """Collect compilestats."""
    from benchbuild.utils.run import track_execution, handle_stdin
    from benchbuild.utils.db import persist_compilestats
    from benchbuild.utils.schema import CompileStat

    clang = handle_stdin(clang["-mllvm", "-stats"], kwargs)

    with track_execution(clang, project, experiment) as run:
        ri = run()

    if ri.retcode == 0:
        stats = []
        for stat in get_compilestats(ri.stderr):
            compile_s = CompileStat()
            compile_s.name = stat["desc"].rstrip()
            compile_s.component = stat["component"].rstrip()
            compile_s.value = stat["value"]
            stats.append(compile_s)
        persist_compilestats(ri.db_run, ri.session, stats)
示例#13
0
    def __call__(self, binary_command, *args, **kwargs):
        self.project.name = kwargs.get("project_name", self.project.name)

        cmd = binary_command[args]
        with run.track_execution(cmd, self.project, self.experiment,
                                 **kwargs) as _run:
            run_info = _run()
            if self.config:
                run_info.add_payload("config", self.config)
                LOG.info(
                    yaml.dump(self.config,
                              width=40,
                              indent=4,
                              default_flow_style=False))
                self.config['baseline'] = \
                    os.getenv("BB_IS_BASELINE", "False")
                db.persist_config(run_info.db_run, run_info.session,
                                  self.config)
        res = self.call_next(binary_command, *args, **kwargs)
        res.append(run_info)
        return res
示例#14
0
文件: run.py 项目: PolyJIT/benchbuild
    def __call__(self, binary_command, *args, **kwargs):
        self.project.name = kwargs.get("project_name", self.project.name)

        cmd = binary_command[args]
        with run.track_execution(cmd, self.project, self.experiment,
                                 **kwargs) as _run:
            run_info = _run()
            if self.config:
                run_info.add_payload("config", self.config)
                LOG.info(
                    yaml.dump(
                        self.config,
                        width=40,
                        indent=4,
                        default_flow_style=False))
                self.config['baseline'] = \
                    os.getenv("BB_IS_BASELINE", "False")
                db.persist_config(run_info.db_run, run_info.session,
                                  self.config)
        res = self.call_next(binary_command, *args, **kwargs)
        res.append(run_info)
        return res
示例#15
0
def collect_compilestats(project, experiment, config, clang, **kwargs):
    """Collect compilestats."""
    from benchbuild.utils.run import track_execution, handle_stdin
    from benchbuild.settings import CFG as c
    from benchbuild.utils.db import persist_compilestats
    from benchbuild.utils.schema import CompileStat

    c.update(config)
    clang = handle_stdin(clang["-mllvm", "-stats"], kwargs)

    with local.env(BB_ENABLE=0):
        with track_execution(clang, project, experiment) as run:
            ri = run()

    if ri.retcode == 0:
        stats = []
        for stat in get_compilestats(ri.stderr):
            compile_s = CompileStat()
            compile_s.name = stat["desc"].rstrip()
            compile_s.component = stat["component"].rstrip()
            compile_s.value = stat["value"]
            stats.append(compile_s)

        components = c["cs"]["components"].value()
        if components is not None:
            stats = [s for s in stats if str(s.component) in components]
        names = c["cs"]["names"].value()
        if names is not None:
            stats = [s for s in stats if str(s.name) in names]

        log = logging.getLogger()
        log.info("\n=========================================================")
        log.info("{:s} results for project {:s}:".format(
            experiment.NAME, project.NAME))
        log.info("=========================================================\n")
        for s in stats:
            log.info("{:s} - {:s}".format(str(s.name), str(s.value)))
        log.info("=========================================================\n")
        persist_compilestats(ri.db_run, ri.session, stats)
示例#16
0
def run_with_papi(project, experiment, config, jobs, run_f, args, **kwargs):
    """
    Run the given file with PAPI support.

    This just runs the project as PAPI support should be compiled in
    already. If not, this won't do a lot.

    Args:
        project: The benchbuild.project.
        experiment: The benchbuild.experiment.
        config: The benchbuild.settings.config.
        jobs: Number of cores we should use for this exection.
        run_f: The file we want to execute.
        args: List of arguments that should be passed to the wrapped binary.
        **kwargs: Dictionary with our keyword args. We support the following
            entries:

            project_name: The real name of our project. This might not
                be the same as the configured project name, if we got wrapped
                with ::benchbuild.project.wrap_dynamic
            has_stdin: Signals whether we should take care of stdin.
    """
    from benchbuild.settings import CFG
    from benchbuild.utils.run import track_execution, handle_stdin
    from benchbuild.utils.db import persist_config

    CFG.update(config)
    project.name = kwargs.get("project_name", project.name)
    run_cmd = local[run_f]
    run_cmd = handle_stdin(run_cmd[args], kwargs)

    with local.env(POLLI_ENABLE_PAPI=1, OMP_NUM_THREADS=jobs):
        with track_execution(run_cmd, project, experiment) as run:
            run_info = run()

    persist_config(run_info.db_run, run_info.session, {"cores": str(jobs)})
示例#17
0
def time_polyjit_and_polly(project: Project, experiment: Experiment,
                           config: Configuration, jobs: int, run_f: str,
                           args: Iterable[str], **kwargs):
    """
    Run the given binary wrapped with time.

    Args:
        project: The benchbuild.project.
        experiment: The benchbuild.experiment.
        config: The benchbuild.settings.config.
        jobs: Number of cores we should use for this execution.
        run_f: The file we want to execute.
        args: List of arguments that should be passed to the wrapped binary.
        **kwargs: Dictionary with our keyword args. We support the following
            entries:

            project_name: The real name of our project. This might not
                be the same as the configured project name, if we got wrapped
                with ::benchbuild.project.wrap_dynamic
            has_stdin: Signals whether we should take care of stdin.
    """
    from benchbuild.utils.run import track_execution, fetch_time_output
    from benchbuild.settings import CFG
    from benchbuild.utils.db import persist_time, persist_config

    CFG.update(config)
    project.name = kwargs.get("project_name", project.name)
    timing_tag = "BB-JIT: "

    may_wrap = kwargs.get("may_wrap", True)

    run_cmd = local[run_f]
    run_cmd = run_cmd[args]
    if may_wrap:
        run_cmd = time["-f", timing_tag + "%U-%S-%e", run_cmd]

    def handle_timing_info(run_info):
        if may_wrap:
            timings = fetch_time_output(timing_tag,
                                        timing_tag + "{:g}-{:g}-{:g}",
                                        run_info.stderr.split("\n"))
            if timings:
                persist_time(run_info.db_run, run_info.session, timings)
            else:
                logging.warning("No timing information found.")
        return run_info

    ri_1 = RunInfo()
    ri_2 = RunInfo()
    with track_execution(run_cmd, project, experiment) as run:
        with local.env(OMP_NUM_THREADS=str(jobs),
                       POLLI_LOG_FILE=CFG["slurm"]["extra_log"].value()):
            ri_1 = handle_timing_info(run())
            persist_config(
                ri_1.db_run, ri_1.session, {
                    "cores": str(jobs - 1),
                    "cores-config": str(jobs),
                    "recompilation": "enabled",
                    "specialization": "enabled"
                })

    with track_execution(run_cmd, project, experiment) as run:
        with local.env(OMP_NUM_THREADS=str(jobs),
                       POLLI_DISABLE_SPECIALIZATION=1,
                       POLLI_LOG_FILE=CFG["slurm"]["extra_log"].value()):
            ri_2 = handle_timing_info(run())
            persist_config(
                ri_2.db_run, ri_2.session, {
                    "cores": str(jobs - 1),
                    "cores-config": str(jobs),
                    "recompilation": "enabled",
                    "specialization": "disabled"
                })

    return ri_1 + ri_2
示例#18
0
 def _track_compilestats(project, experiment, _, clang):
     """Compile the project and track the compilestats."""
     clang = clang["-mllvm", "-polli-collect-modules"]
     with run.track_execution(clang, project, experiment) as command:
         command()
示例#19
0
    def __call__(self, cc, *args, **kwargs):
        """
        Generates custom sequences using the first genetic opt algorithms.

        Args:
            project: The name of the project the test is being run for.
            experiment: The benchbuild.experiment.
            config: The config from benchbuild.settings.
            jobs: Number of cores to be used for the execution.
            run_f: The file that needs to be execute.
            args: List of arguments that will be passed to the wrapped binary.
            kwargs: Dictonary with the keyword arguments.

        Returns:
            The generated custom sequences as a list.
        """
        seq_to_fitness = {}
        gene_pool, _, _ = get_defaults()
        chromosome_size, population_size, generations = get_genetic_defaults()
        run_info = run.track_execution(cc, self.project, self.experiment)

        def crossover(upper_half):
            """
            Crossover of two genes.

            This crosses two gense and fills the vacancies in the population by
            using two random chromosomes and recombine their halfs.
            """
            random1 = random.choice(upper_half)
            random2 = random.choice(upper_half)
            half_index = len(random1) // 2

            new_chromosomes = [
                random1[:half_index] + random2[half_index:],
                random1[half_index:] + random2[:half_index],
                random2[:half_index] + random1[half_index:],
                random2[half_index:] + random1[:half_index]
            ]

            return new_chromosomes

        def simulate_generation(chromosomes, gene_pool, seq_to_fitness):
            """Simulate the change of a population in a single generation."""
            # calculate the fitness value of each chromosome
            jobs = CFG["jobs"].value * 5
            with cf.ThreadPoolExecutor(jobs) as pool:
                future_to_fitness = extend_gene_future([], chromosomes, pool)

                for future_fitness in cf.as_completed(future_to_fitness):
                    key, fitness = future_fitness.result()
                    old_fitness = seq_to_fitness.get(key, sys.maxsize)
                    seq_to_fitness[key] = min(old_fitness, int(fitness))
            # sort the chromosomes by their fitness value
            chromosomes.sort(key=lambda c: seq_to_fitness[str(c)],
                             reverse=True)

            # divide the chromosome into two halves and delete the weakest one
            index_half = len(chromosomes) // 2
            lower_half = chromosomes[:index_half]
            upper_half = chromosomes[index_half:]

            # delete four weak chromosomes
            del lower_half[0]
            random.shuffle(lower_half)

            for _ in range(0, 3):
                lower_half.pop()

            new_chromosomes = crossover(upper_half)

            # mutate the fittest chromosome of this generation
            fittest_chromosome = upper_half.pop()
            lower_half = mutate(lower_half, gene_pool, 10)
            upper_half = mutate(upper_half, gene_pool, 5)

            # rejoin all chromosomes
            upper_half.append(fittest_chromosome)
            chromosomes = lower_half + upper_half + new_chromosomes

            return chromosomes, fittest_chromosome

        def generate_random_gene_sequence(gene_pool):
            """Generates a random sequence of genes."""
            genes = []
            for _ in range(chromosome_size):
                genes.append(random.choice(gene_pool))

            return genes

        def extend_gene_future(future_to_fitness, chromosomes, pool):
            def fitness(lhs, rhs):
                """Defines the fitnesses metric."""
                return (lhs - rhs) / rhs

            future_to_fitness.extend([
                pool.submit(self.call_next, opt_cmd, str(chromosome),
                            chromosome, fitness) for chromosome in chromosomes
            ])
            return future_to_fitness

        def delete_duplicates(chromosomes, gene_pool):
            """Deletes duplicates in the chromosomes of the population."""
            new_chromosomes = []
            for chromosome in chromosomes:
                new_chromosomes.append(tuple(chromosome))

            chromosomes = []
            new_chromosomes = list(set(new_chromosomes))
            diff = population_size - len(new_chromosomes)

            if diff > 0:
                for _ in range(diff):
                    chromosomes.append(
                        generate_random_gene_sequence(gene_pool))

            for chromosome in new_chromosomes:
                chromosomes.append(list(chromosome))

            return chromosomes

        def mutate(chromosomes, gene_pool, mutation_probability):
            """Performs mutation on chromosomes with a certain probability."""
            mutated_chromosomes = []

            for chromosome in chromosomes:
                mutated_chromosome = list(chromosome)
                chromosome_size = len(mutated_chromosome)

                for i in range(chromosome_size):
                    if random.randint(1, 100) <= mutation_probability:
                        mutated_chromosome[i] = random.choice(gene_pool)

                mutated_chromosomes.append(mutated_chromosome)

            return mutated_chromosomes

        with run.track_execution(cc, self.project, self.experiment) as tracked:
            run_info = tracked()
        filter_compiler_commandline(cc, filter_invalid_flags)
        complete_ir = link_ir(cc)
        from benchbuild.utils.cmd import opt
        opt_cmd = opt[complete_ir, "-disable-output", "-stats"]
        chromosomes = []
        fittest_chromosome = []

        for _ in range(population_size):
            chromosomes.append(generate_random_gene_sequence(gene_pool))

        for i in range(generations):
            chromosomes, fittest_chromosome = simulate_generation(
                chromosomes, gene_pool, seq_to_fitness)
            if i < generations - 1:
                chromosomes = delete_duplicates(chromosomes, gene_pool)

        persist_sequence(run_info, fittest_chromosome,
                         seq_to_fitness[str(fittest_chromosome)])
示例#20
0
    def __call__(self, cc, *args, **kwargs):
        """
        Generates custom sequences for a provided application using the second
        genetic opt algorithm.

        Args:
            project: The name of the project the test is being run for.
            experiment: The benchbuild.experiment.
            config: The config from benchbuild.settings.
            jobs: Number of cores to be used for the execution.
            run_f: The file that needs to be execute.
            args: List of arguments that will be passed to the wrapped binary.
            kwargs: Dictonary with the keyword arguments.

        Returns:
            The generated custom sequence.
        """
        seq_to_fitness = {}
        gene_pool, _, _ = get_defaults()
        chromosome_size, population_size, generations = get_genetic_defaults()

        def generate_random_gene_sequence(gene_pool):
            """Generates a random sequence of genes."""
            genes = []
            for _ in range(chromosome_size):
                genes.append(random.choice(gene_pool))

            return genes

        def extend_gene_future(future_to_fitness, chromosomes, pool):
            """Extend with future values from the chromosomes."""
            def fitness(lhs, rhs):
                """Defines the fitnesses metric."""
                return (lhs - rhs) / rhs

            future_to_fitness.extend([
                pool.submit(self.call_next, opt_cmd, str(chromosome),
                            chromosome, fitness) for chromosome in chromosomes
            ])
            return future_to_fitness

        def delete_duplicates(chromosomes, gene_pool):
            """Deletes duplicates in the chromosomes of the population."""
            new_chromosomes = []
            for chromosome in chromosomes:
                new_chromosomes.append(tuple(chromosome))

            chromosomes = []
            new_chromosomes = list(set(new_chromosomes))
            diff = population_size - len(new_chromosomes)

            if diff > 0:
                for _ in range(diff):
                    chromosomes.append(
                        generate_random_gene_sequence(gene_pool))

            for chromosome in new_chromosomes:
                chromosomes.append(list(chromosome))

            return chromosomes

        def mutate(chromosomes, gene_pool, mutation_probability):
            """Performs mutation on chromosomes with a certain probability."""
            mutated_chromosomes = []

            for chromosome in chromosomes:
                mutated_chromosome = list(chromosome)
                chromosome_size = len(mutated_chromosome)

                for i in range(chromosome_size):
                    if random.randint(1, 100) <= mutation_probability:
                        mutated_chromosome[i] = random.choice(gene_pool)

                mutated_chromosomes.append(mutated_chromosome)

            return mutated_chromosomes

        def crossover(fittest_chromosome, best_chromosomes):
            """
            Crossover two genes and fill the vacancies in the population by
            taking two of the fittest chromosomes and recombining them.
            """
            new_chromosomes = []
            num_of_new = population_size - len(best_chromosomes)
            half_index = len(fittest_chromosome) // 2

            while len(new_chromosomes) < num_of_new:
                best1 = random.choice(best_chromosomes)
                best2 = random.choice(best_chromosomes)
                new_chromosomes.append(best1[:half_index] + best2[half_index:])
                if len(new_chromosomes) < num_of_new:
                    new_chromosomes.append(best1[half_index:] +
                                           best2[:half_index])
                if len(new_chromosomes) < num_of_new:
                    new_chromosomes.append(best2[:half_index] +
                                           best1[half_index:])
                if len(new_chromosomes) < num_of_new:
                    new_chromosomes.append(best2[half_index:] +
                                           best1[:half_index])

            return new_chromosomes

        def simulate_generation(chromosomes, gene_pool, seq_to_fitness):
            """Simulate the change of a population in a single generation."""
            # calculate the fitness value of each chromosome
            jobs = CFG["jobs"].value * 5
            with cf.ThreadPoolExecutor(jobs) as pool:
                future_to_fitness = extend_gene_future([], chromosomes, pool)

                for future_fitness in cf.as_completed(future_to_fitness):
                    key, fitness = future_fitness.result()
                    old_fitness = seq_to_fitness.get(key, sys.maxsize)
                    seq_to_fitness[key] = min(old_fitness, int(fitness))
            # sort the chromosomes by their fitness value
            chromosomes.sort(key=lambda c: seq_to_fitness[str(c)],
                             reverse=True)

            # best 10% of chromosomes survive without change
            num_best = len(chromosomes) // 10
            fittest_chromosome = chromosomes.pop()
            best_chromosomes = [fittest_chromosome]
            for _ in range(num_best - 1):
                best_chromosomes.append(chromosomes.pop())

            new_chromosomes = crossover(fittest_chromosome, best_chromosomes)

            # mutate the new chromosomes
            new_chromosomes = mutate(new_chromosomes, gene_pool, 10)

            # rejoin all chromosomes
            chromosomes = best_chromosomes + new_chromosomes

            return chromosomes, fittest_chromosome

        with run.track_execution(cc, self.project, self.experiment) as tracked:
            run_info = tracked()
        filter_compiler_commandline(cc, filter_invalid_flags)
        complete_ir = link_ir(cc)
        from benchbuild.utils.cmd import opt
        opt_cmd = opt[complete_ir, "-disable-output", "-stats"]
        chromosomes = []
        fittest_chromosome = []

        for _ in range(population_size):
            chromosomes.append(generate_random_gene_sequence(gene_pool))

        for i in range(generations):
            chromosomes, fittest_chromosome = \
                simulate_generation(chromosomes, gene_pool, seq_to_fitness)
            if i < generations - 1:
                chromosomes = delete_duplicates(chromosomes, gene_pool)

        persist_sequence(run_info, fittest_chromosome,
                         seq_to_fitness[str(fittest_chromosome)])
示例#21
0
    def __call__(self, cc, *args, **kwargs):
        seq_to_fitness = {}
        pass_space, seq_length, iterations = get_defaults()

        def fitness(lhs, rhs):
            """Defines the fitnesses metric."""
            return lhs - rhs

        def extend_future(sequence, pool):
            """
            Generate the future of the fitness values from the sequence.
            """
            neighbours = []
            future_to_fitness = []

            # generate the neighbours of the current base sequence
            for i in range(seq_length):
                remaining_passes = list(pass_space)
                remaining_passes.remove(sequence[i])

                for remaining_pass in remaining_passes:
                    neighbour = list(sequence)
                    neighbour[i] = remaining_pass
                    neighbours.append(neighbour)

                future_to_fitness.extend([
                    pool.submit(self.call_next, opt_cmd, str(sequence),
                                sequence, fitness)
                ])

            future_to_fitness.extend([
                pool.submit(self.call_next, opt_cmd, str(neighbour), neighbour,
                            fitness) for neighbour in neighbours
            ])

            return future_to_fitness, neighbours

        def create_random_sequence(pass_space, seq_length):
            """Creates a random sequence."""
            sequence = []
            for _ in range(seq_length):
                sequence.append(random.choice(pass_space))

            return sequence

        def climb(sequence, seq_to_fitness):
            """
            Find the best sequence and calculate all of its neighbours. If the
            best performing neighbour is fitter than the base sequence,
            the neighbour becomes the new base sequence. Repeat until the base
            sequence has the best performance compared to its neighbours.
            """
            changed = True
            future_to_fitness = []
            base_sequence = sequence
            base_sequence_key = str(sequence)
            with cf.ThreadPoolExecutor(max_workers=CFG["jobs"].value * 5) \
                    as pool:
                while changed:
                    changed = False
                    future_to_fitness, neighbours = \
                        extend_future(base_sequence, pool)
                    for future_fitness in cf.as_completed(future_to_fitness):
                        key, fitness_val = future_fitness.result()
                        old_fitness = seq_to_fitness.get(key, sys.maxsize)
                        seq_to_fitness[key] = min(old_fitness, fitness_val)

                    for neighbour in neighbours:
                        if seq_to_fitness[base_sequence_key] \
                                > seq_to_fitness[str(neighbour)]:
                            base_sequence = neighbour
                            base_sequence_key = str(neighbour)
                            changed = True

            return base_sequence, seq_to_fitness

        with run.track_execution(cc, self.project, self.experiment) as tracked:
            run_info = tracked()
        filter_compiler_commandline(cc, filter_invalid_flags)
        complete_ir = link_ir(cc)
        from benchbuild.utils.cmd import opt
        opt_cmd = opt[complete_ir, "-disable-output", "-stats"]

        best_sequence = []
        seq_to_fitness = multiprocessing.Manager().dict()

        for _ in range(iterations):
            base_sequence = create_random_sequence(pass_space, seq_length)
            best_sequence, seq_to_fitness = \
                climb(base_sequence, seq_to_fitness)

            if not best_sequence or seq_to_fitness[str(best_sequence)] \
                    > seq_to_fitness[str(base_sequence)]:
                best_sequence = base_sequence

        persist_sequence(run_info, best_sequence,
                         seq_to_fitness[str(best_sequence)])
示例#22
0
    def __call__(self, cc, *args, **kwargs):
        seq_to_fitness = {}
        generated_sequences = []
        pass_space, seq_length, iterations = get_defaults()

        def extend_future(base_sequence, pool):
            """Generate the future of the fitness values from the sequences."""
            def fitness(lhs, rhs):
                """Defines the fitnesses metric."""
                return lhs - rhs

            future_to_fitness = []
            sequences = []
            for flag in pass_space:
                new_sequences = []
                new_sequences.append(list(base_sequence) + [flag])
                if base_sequence:
                    new_sequences.append([flag] + list(base_sequence))

                sequences.extend(new_sequences)
                future_to_fitness.extend([
                    pool.submit(self.call_next, opt_cmd, str(seq), seq,
                                fitness) for seq in new_sequences
                ])
            return future_to_fitness, sequences

        def create_greedy_sequences():
            """
            Create an optimal sequence, using a greedy algorithm.

            Return: A list of the fittest generated sequences.
            """

            jobs = CFG["jobs"].value * 5
            with cf.ThreadPoolExecutor(max_workers=jobs) as pool:
                for _ in range(iterations):
                    base_sequence = []
                    while len(base_sequence) < seq_length:
                        future_to_fitness, sequences = \
                            extend_future(base_sequence, pool)

                        for future_fitness in cf.as_completed(
                                future_to_fitness):
                            key, fitness = future_fitness.result()
                            old_fitness = seq_to_fitness.get(key, sys.maxsize)
                            seq_to_fitness[key] = min(old_fitness, fitness)

                        sequences.sort(key=lambda s: seq_to_fitness[str(s)],
                                       reverse=True)

                        fittest = sequences.pop()
                        fittest_fitness_value = seq_to_fitness[str(fittest)]
                        fittest_sequences = [fittest]

                        next_fittest = fittest
                        while next_fittest == fittest and len(sequences) > 1:
                            next_fittest = sequences.pop()
                            if seq_to_fitness[str(next_fittest)] == \
                                    fittest_fitness_value:
                                fittest_sequences.append(next_fittest)

                        base_sequence = random.choice(fittest_sequences)
                generated_sequences.append(base_sequence)
            return generated_sequences

        with run.track_execution(cc, self.project, self.experiment) as tracked:
            run_info = tracked()
        filter_compiler_commandline(cc, filter_invalid_flags)
        complete_ir = link_ir(cc)
        from benchbuild.utils.cmd import opt
        opt_cmd = opt[complete_ir, "-disable-output", "-stats"]

        generated_sequences = create_greedy_sequences()
        generated_sequences.sort(key=lambda s: seq_to_fitness[str(s)],
                                 reverse=True)
        max_fitness = 0
        for seq in generated_sequences:
            cur_fitness = seq_to_fitness[str(seq)]
            max_fitness = max(max_fitness, cur_fitness)
        fittest_sequence = generated_sequences.pop()
        persist_sequence(run_info, fittest_sequence, max_fitness)