diff --git a/mix-object.ts b/mix-object.ts new file mode 100644 index 0000000..084b002 --- /dev/null +++ b/mix-object.ts @@ -0,0 +1,150 @@ +/** + * 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();