返回 dev

bench_blur.mjs

dev/bench_blur.mjs · 3.8 KB · 92 行
dev/bench_blur.mjs 3.8 KB · 92 行 GitHub
// 盒式模糊 A/B 微基准:新旧两版实现在同一份数据上跑,避开整条管线的机器抖动// 用法: node dev/bench_blur.mjs [W] [H] [重复次数]const W = +(process.argv[2] || 1024), H = +(process.argv[3] || 1024), REP = +(process.argv[4] || 5);const N = W * H;const rnd = (() => { let s = 12345; return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; })();const cr = new Float32Array(N), cg = new Float32Array(N), cb = new Float32Array(N);for (let i = 0; i < N; i++) { cr[i] = rnd() * 255; cg[i] = rnd() * 255; cb[i] = rnd() * 255; }function blurOld(cr, cg, cb) {  for (let it = 0; it < 4; it++) {    const nr = new Float32Array(cr), ng = new Float32Array(cg), nb = new Float32Array(cb);    for (let y = 0; y < H; y++) {      for (let x = 0; x < W; x++) {        const p = y * W + x;        let sr = 0, sg = 0, sb = 0, cnt = 0;        for (let dy = -1; dy <= 1; dy++) {          const yy = y + dy; if (yy < 0 || yy >= H) continue;          for (let dx = -1; dx <= 1; dx++) {            const xx = x + dx; if (xx < 0 || xx >= W) continue;            const q = yy * W + xx;            sr += cr[q]; sg += cg[q]; sb += cb[q]; cnt++;          }        }        nr[p] = sr / cnt; ng[p] = sg / cnt; nb[p] = sb / cnt;      }    }    cr.set(nr); cg.set(ng); cb.set(nb);  }  return [cr, cg, cb];}function blurNew(cr, cg, cb) {  let curR = cr, curG = cg, curB = cb;  let nxtR = new Float32Array(N), nxtG = new Float32Array(N), nxtB = new Float32Array(N);  const generic = (x, y) => {    const p = y * W + x;    let sr = 0, sg = 0, sb = 0, cnt = 0;    for (let dy = -1; dy <= 1; dy++) {      const yy = y + dy; if (yy < 0 || yy >= H) continue;      for (let dx = -1; dx <= 1; dx++) {        const xx = x + dx; if (xx < 0 || xx >= W) continue;        const q = yy * W + xx;        sr += curR[q]; sg += curG[q]; sb += curB[q]; cnt++;      }    }    nxtR[p] = sr / cnt; nxtG[p] = sg / cnt; nxtB[p] = sb / cnt;  };  for (let it = 0; it < 4; it++) {    if (W >= 3 && H >= 3) {      for (let y = 1; y < H - 1; y++) {        const yc = y * W;        for (let x = 1; x < W - 1; x++) {          const p = yc + x;          let sr = 0, sg = 0, sb = 0;          for (let dy = -1; dy <= 1; dy++) {            const row = yc + dy * W;            for (let dx = -1; dx <= 1; dx++) { const q = row + x + dx; sr += curR[q]; sg += curG[q]; sb += curB[q]; }          }          nxtR[p] = sr / 9; nxtG[p] = sg / 9; nxtB[p] = sb / 9;        }      }      for (let x = 0; x < W; x++) { generic(x, 0); generic(x, H - 1); }      for (let y = 1; y < H - 1; y++) { generic(0, y); generic(W - 1, y); }    } else {      for (let y = 0; y < H; y++) for (let x = 0; x < W; x++) generic(x, y);    }    { const t = curR; curR = nxtR; nxtR = t; }    { const t = curG; curG = nxtG; nxtG = t; }    { const t = curB; curB = nxtB; nxtB = t; }  }  if (curR !== cr) { cr.set(curR); cg.set(curG); cb.set(curB); }  return [cr, cg, cb];}// 先各跑一次预热let a = blurOld(cr.slice(), cg.slice(), cb.slice());let b = blurNew(cr.slice(), cg.slice(), cb.slice());let diff = 0, mx = 0;for (let i = 0; i < N; i++) {  for (const [u, v] of [[a[0][i], b[0][i]], [a[1][i], b[1][i]], [a[2][i], b[2][i]]]) {    if (u !== v) { diff++; const d = Math.abs(u - v); if (d > mx) mx = d; }  }}console.log(`逐位对比:不同的通道值 ${diff} / ${N * 3}   最大差 ${mx}`);let tOld = Infinity, tNew = Infinity;for (let i = 0; i < REP; i++) {  let t = Date.now(); blurOld(cr.slice(), cg.slice(), cb.slice()); tOld = Math.min(tOld, Date.now() - t);  t = Date.now(); blurNew(cr.slice(), cg.slice(), cb.slice()); tNew = Math.min(tNew, Date.now() - t);}console.log(`旧版 ${(tOld / 1000).toFixed(2)}s   新版 ${(tNew / 1000).toFixed(2)}s   提速 ${(tOld / tNew).toFixed(2)}×(${W}x${H},取 ${REP} 次最小值)`);