/** * Binary search the first bad object in object sets. * Things todo: * 1. Determine the set of vector, or scalar version. * 2. Use the mechanism above, construct such set * 3. Link the set to an executable -> SPEC path, invoke "runcpu" */ import { binSearch } from "./algorithm"; import { pop2, defaultSPEC, SPEC, Bench, mkBench } from "./spec"; import path from "path"; import { FLANG, PREFIX, SYSROOT_PREFIX } from "./environment"; import { generalCommand, linkerCommand } from "./commands/compiler"; import { runcpuOptions } from "./commands/spec"; import { renderConfig } from "./spec"; import { checkedSpawnSync } from "./cli"; import { systemdRunOptions } from "./commands/systemd"; export interface Linkable { link: (objectPath: (objectNames: string[]) => string[]) => Promise; } function mkPop2Bench(spec: SPEC): Bench & Linkable { const base = mkBench(spec, pop2); return { ...base, async link(objectPath) { // Set up environment variables. // FIXME: use -rpath or -rpath-link after I find out why. const linkenv = { ...process.env }; linkenv.LD_LIBRARY_PATH = [ path.join(PREFIX, 'lib'), path.join(SYSROOT_PREFIX, 'lib'), path.join(SYSROOT_PREFIX, 'usr', 'lib') ].join(':'); const objects = objectPath(base.benchData().objectNames); const options = [ ...objects, ...linkerCommand({ searchDirs: [path.join(PREFIX, "lib"),], }), ...generalCommand({ output: base.exepath(), outputKind: "exe", sysroot: SYSROOT_PREFIX, }), ]; // Execute the link command const proc = checkedSpawnSync(FLANG, options, { stdio: "inherit", env: linkenv, }); if (proc.error) { throw proc.error; } }, }; } async function main() { const spec = defaultSPEC; // Path to SPEC2017 test suite. spec.setenv(); // Just use scalar vanilla version of grid, will it work? // // No, does not work. const useVectorGrid = (object: string) => object !== "grid.fppized.o"; const length = pop2.objectNames.length; const beforeHalf = [ // Empty: /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.664.fpspeed.refspeed.txt // 0.336 false, ]; const [vBegin, vHalf, vEnd] = binSearch(0, length, beforeHalf); // use scalar version if index is in this range. const scalarRange = [ [0, length / 2], [length / 2, length], ]; const useVectors = scalarRange.map(([a, b]) => ({ useVector: (_: string, index: number) => { // If index is not in range [a, b), use the vector version. return !(a <= index && index < b); }, range: [a, b], })); // Linking each "useVector" instances in sequence for (const { useVector: predicate, range } of useVectors) { const buildPathObj = (build: string) => (objname: string) => path.join(spec.buildpath(pop2), build, objname); const vector = buildPathObj("build_vector"); const scalar = buildPathObj("build_scalar_vanilla"); const pop2Bench = mkPop2Bench(spec); console.log(`Linking objects. Range in [${range[0]}, ${range[1]}) used scalar version. others are vector version.`); await pop2Bench.link(names => names.map((obj, index) => predicate(obj, index) ? vector(obj) : scalar(obj))); const config = "clang-O2.cfg"; const serviceName = `${pop2Bench.benchData().num}-${range[0]}-${range[1]}`; // Render the config if necessary. if (false) { await spec.newConfig(config, renderConfig({ gccdir: PREFIX, optimize: "-O2", })); } checkedSpawnSync("systemd-run", [ ...systemdRunOptions({ scope: false, unit: `spec-${serviceName}`, user: true, }), "runcpu", ...runcpuOptions({ benchmarks: [pop2Bench.benchData().num.toString()], config, workload: "ref", buildType: "nobuild", outputFormat: ["text", "config"] }), ], { stdio: "inherit" }); } } main();