diff --git a/mix-object.ts b/mix-object.ts index 507d482..74719da 100644 --- a/mix-object.ts +++ b/mix-object.ts @@ -12,9 +12,9 @@ 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 { checkedSpawnSync, promisifySpawn } from "./cli"; import { systemdRunOptions } from "./commands/systemd"; +import { spawn } from "child_process"; export interface Linkable { link: (objectPath: (objectNames: string[]) => string[]) => Promise; @@ -62,142 +62,118 @@ function mkPop2Bench(spec: SPEC): Bench & Linkable { } -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"; +// Bisect results. - 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. - const beforeHalfGrid = [ - // 0.336 + 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 - // 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, + // Vector [241, 281): Error, + // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.674.fpspeed.refspeed.txt + // Vector [281, 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 + true, + // Vector [241, 261): Error, + // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.675.fpspeed.refspeed.rsf + // Vector [261, 281): Correct. - false, - // Vector [241, 281): Error, - // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.674.fpspeed.refspeed.txt - // Vector [281, 322): 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, 261): Error, - // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.675.fpspeed.refspeed.rsf - // Vector [261, 281): Correct. + true, + // Vector [241, 246): Error, + // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.677.fpspeed.refspeed.rsf +]; - true, - // Vector [241, 251): Error, - // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.676.fpspeed.refspeed.txt - // Vector [251, 261): Stopped. +const beforeHalfNoGrid: boolean[] = [ + false, - true, - // Vector [241, 246): Error, - // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.677.fpspeed.refspeed.rsf - ]; + // 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, - const beforeHalfNoGrid: boolean[] = [ + // Vector [201, 221): Error + // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.681 + // Vector [221, 241): Unknown + true, - false, + // Vector [201, 211): Error + // Vector [211, 221): Unknown + true, - // Vector [161, 241): Error - // /home/lyc/workspace/sw-autovec/spec2017/result/CPU2017.679. - // Vector [241, 322): Unknown - true, + // Vector [201, 206): Unknown + // Vector [206, 211): Error + false, - // Vector [161, 201): Unknown - // Vector [201, 241): Error - false, + // Vector [206, 208): Error + // Vector [208, 211): ? + true, - // 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); + // Vector [206, 207): ? + // !!! Vector [207, 208): Error +]; +async function bisect( + beforeHalf: boolean[], + /** specify which spec to use */ + rangeSPEC: (range: [number, number], index: number) => SPEC, + /** How to get the vector object path */ + vector: (name: string) => string, + /** And how to get scalar path. */ + scalar: (name: string) => string, +) { + const [vBegin, vHalf, vEnd] = binSearch(0, pop2.objectNames.length, beforeHalf); // use scalar version if index is in this range. - const vectorRange: number[][] = [ - [0, length], - // [vBegin, vHalf], - // [vHalf, vEnd], + const vectorRange: [number, number][] = [ + [vBegin, vHalf], + [vHalf, vEnd], ]; - const specs = [ - path.join(SW_AUTOVEC, "spec2017"), - path.join(SW_AUTOVEC, "spec2017-2") - ].map(mkSPEC); + await Promise.all(vectorRange.map((range, index) => ({ + range, + // Assign each range a dedicated SPEC, to avoid race conditions. + spec: rangeSPEC(range, index), + })).map(async ({ range, spec }) => { + // For each range, linking the objects and test it. - 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 [a, b] = range; const pop2Bench = mkPop2Bench(spec); - console.log(`Linking objects. Range in [${range[0]}, ${range[1]}) used vector version. others are scalar version.`); - + console.log(`Linking objects. Range in [${a}, ${b}) 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", + names.map((name, index) => { + if (name === "grid.fppized.o" || index == 207) { + console.log(`${name} is a bad object!`); + return scalar(name); + } + // If index is in range [a, b), use the vector version. + return a <= index && index < b ? vector(name) : scalar(name); })); - } + + const serviceName = `${pop2Bench.benchData().num}-${a}-${b}`; checkedSpawnSync("systemd-run", [ @@ -209,13 +185,87 @@ async function main() { "runcpu", ...runcpuOptions({ benchmarks: [pop2Bench.benchData().num.toString()], - config, + config: "clang-O2.cfg", workload: "ref", buildType: "nobuild", outputFormat: ["text", "config"] }), ], { stdio: "inherit", env: spec.getEnvironment() }); })); -} +}; -main(); +(async () => { + + const buildPathObj = (buildBase: string) => (build: string) => (objname: string) => path.join(buildBase, build, objname); + const buildDirs = ["build_vector", "build_scalar_vanilla"]; + + const specs = [ + "spec2017", + "spec2017-2", + ].map(s => path.resolve(SW_AUTOVEC, s)).map(mkSPEC); + + // To test which version works, for grid. + await (async (spec: SPEC) => { + const pop2Bench = mkPop2Bench(spec); + + const [vector, scalar] = buildDirs.map(dir => buildPathObj(spec.buildpath(pop2))(dir)); + + await pop2Bench.link(names => { + return names.flatMap(p => { + if (p == "grid.fppized.o") { + const functionList = [ + "grid_.o", + "grid_area_masks_.o", + "grid_calc_tpoints_.o", + "grid_cf_area_avg_.o", + "grid_compute_dz_.o", + "grid_fill_points_.o", + "grid_horiz_grid_internal_.o", + "grid_init_grid1_.o", + "grid_init_grid2_.o", + "grid_landmasks_.o", + "grid_read_bottom_cell_.o", + "grid_read_horiz_grid_.o", + "grid_read_topography_.o", + "grid_read_vert_grid_.o", + "grid_remove_isolated_points_.o", + "grid_remove_points_.o", + "grid_smooth_topography_.o", + "grid_tgrid_to_ugrid_.o", + "grid_topography_bathymetry_.o", + "grid_topography_internal_.o", + "grid_ugrid_to_tgrid_.o", + "grid_vert_grid_internal_.o", + ]; + return [ + ...functionList.map(fn => { + const getFunc = (name: string) => path.join(spec.buildpath(pop2), name, fn); + return fn == "grid_landmasks_.o" ? getFunc("function_scalar") : getFunc("function_simd"); + }), + path.join(spec.buildpath(pop2), "global-obj.ll.o") + ]; + } + return vector(p); + }); + }); + + await promisifySpawn(spawn("systemd-run", + [ + ...systemdRunOptions({ + scope: true, + user: true, + unit: "pop2-grid-test", + }), + "runcpu", + ...runcpuOptions({ + benchmarks: [pop2Bench.benchData().num.toString()], + config: "clang-O2", + workload: "test", + buildType: "nobuild", + outputFormat: ["text", "config"] + }), + ], { stdio: "inherit", env: spec.getEnvironment() })); + + })(specs[0]); + +})();