Files
work-ts/mix-object.ts

222 lines
6.9 KiB
TypeScript

/**
* 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<void>;
}
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();