/** * 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, SPEC, Bench, mkBench, mkSPEC } from "./spec"; import path from "path"; import { FLANG, PREFIX, SW_AUTOVEC, 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() { // 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 beforeHalfGrid = [ // 0.336 // Scalar [0, 161): Error, // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.671.fpspeed.refspeed.txt // : /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.664.fpspeed.refspeed.txt // Scalar [161, 322): Correct. false, // Scalar [161, 241): Error, // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.672.fpspeed.refspeed.txt // Scalar [241, 322): Error, // /home/lyc/workspace/sw-autovec/spec2017-2/result/CPU2017.672.fpspeed.refspeed.rsf // Vector [161, 241): Error, // Vector [241, 322): Error, // /home/lyc/workspace/sw-autovec/spec2017-2/result/CPU2017.673.fpspeed.refspeed.txt false, // Vector [241, 281): Error, // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.674.fpspeed.refspeed.txt // Vector [281, 322): Correct. true, // Vector [241, 261): Error, // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.675.fpspeed.refspeed.rsf // Vector [261, 281): Correct. true, // Vector [241, 251): Error, // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.676.fpspeed.refspeed.txt // Vector [251, 261): Stopped. true, // Vector [241, 246): Error, // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.677.fpspeed.refspeed.rsf ]; const beforeHalfNoGrid: boolean[] = [ false, // Vector [161, 241): Error // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.679. // Vector [241, 322): Unknown true, // Vector [161, 201): Unknown // Vector [201, 241): Error false, // Vector [201, 221): Error // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.681 // Vector [221, 241): Unknown true, // Vector [201, 211): Error // Vector [211, 221): Unknown true, // Vector [201, 206): Unknown // Vector [206, 211): Error false, // Vector [206, 208): Error // Vector [208, 211): ? true, // Vector [206, 207): ? // !!! Vector [207, 208): Error ]; const [vBegin, vHalf, vEnd] = binSearch(0, length, beforeHalfNoGrid); // use scalar version if index is in this range. const vectorRange: number[][] = [ [0, length], // [vBegin, vHalf], // [vHalf, vEnd], ]; const specs = [ path.join(SW_AUTOVEC, "spec2017"), path.join(SW_AUTOVEC, "spec2017-2") ].map(mkSPEC); const useVectors = vectorRange.map(([a, b], index) => ({ useVector: (name: string, index: number) => { if (name === "grid.fppized.o") return false; if (index == 207) { console.log(`${name} is a bad object!`); return false; } // If index is in range [a, b), use the vector version. return a <= index && index < b; }, range: [a, b], spec: specs[index], })); await Promise.all(useVectors.map(async ({ useVector, range, spec }) => { 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 vector version. others are scalar version.`); await pop2Bench.link(names => names.map((obj, index) => useVector(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", env: spec.getEnvironment() }); })); } main();