Repository navigation
SA and VU power scaled by the unit count twice on the enable_dvfs=False branch #7
Description
I tried reproducing the six per-component static-energy share ranges reported in section 3,
pages 4 and 5 of the ReGate paper, and could not with NeuSim at 58fbd3f. After debugging on
the assumption it was a problem with my configs, I noticed num_sa and num_vu are applied
twice.
ChipConfig.static_power_sa_W is already a whole-chip value:
# neusim/configs/chips/ChipConfig.py:119-120
def static_power_sa_W(self) -> float:
return self.static_power_W_per_sa * self.num_saanalyze_sa_static_energy multiplies it by num_sa again, outside the branch:
# neusim/npusim/backend/power_model.py:194-198
if config.enable_dvfs:
_, static_sa_W = get_power_from_dvfs("SA", op.dvfs_sa) # per-SA
else:
static_sa_W = config.static_power_sa_W # already per_sa * num_sa
static_sa_W *= config.num_sa # hits both branchesThe multiply looks intended for the DVFS branch, whose table is per-unit
(neusim/npusim/backend/dvfs_power_getter.py:43, "SA and VU points are for a single SA/VU").
Since it sits outside the if, it also applies to the branch whose input is already a chip
total. enable_dvfs defaults to False (ChipConfig.py:93), so that is the branch that runs
unless --dvfs_policy is set to a non-default value
(neusim/run_scripts/energy_operator_analysis_main.py:85-86).
Four sites: SA static (:198), VU static (:370), SA/VU dynamic (:178-179).
What it does
llama3-8b decode on tpuv5p, batch 1, NoPG. Share of static energy:
| component | ReGate §3 | frozen artifact | NeuSim |
|---|---|---|---|
| SA | 8-14% | 9.5 | 43.9 |
| VU | 1.9-5.6% | 2.5 | 8.6 |
Feeding identical operator statistics to both power models, the ratio is exactly num_sa on
SA and num_vu on VU across all seven chip configs, and 1.000 on the four components the
multiply does not touch.
The chip constants agree with the single multiply independently of the artifact: summing the
six static components once gives each chip's stored idle_power_W exactly on tpuv2, tpuv3
and tpuv4 (53.000 / 84.000 / 90.000 W). With the second multiply none of them match.
Reproducing
https://github.com/lifrankfan/neusim-power-double-count
./run_all.sh regenerates everything against NeuSim 58fbd3f and the
MICRO'25 artifact at 004dbfc. Full output is committed as RESULTS.txt.
What I have not established
- Why the line is there. The public history in both repositories starts with a squashed drop
that already contains it, so nothing I can see says whether it was deliberate. - 24 of the 1680 cells carry a second difference besides the power model. All are tpuv5p,
which the artifact clocks at 1.75 GHz and NeuSim at 1.70. Frequency feeds the FLOPS
utilization that scales dynamic energy, so those ratios read 8.235 rather than 8.000
(8 x 1.75/1.70). The other six chips are clean.
My question
Is the unit-count scaling at those four sites meant for the DVFS branch only, and should the
default branch use static_power_sa_W as ChipConfig already defines it?
If that is the right reading, I have a patch that moves the multiply inside the branch rather
than deleting it (the DVFS branch needs it): patches/fix-double-multiply.patch in the repo
above. Happy to open it as a PR, but it changes reported SA and VU energy on the default path,
so that seemed like your call rather than mine.
Activity
XZman commentedon Sep 2, 2026
Thank you very much for your bug report, Frank!
As your patch suggests, the line
static_sa_W *= config.num_sashould go inside the dvfs branch of that if statement. This happens accidentally when I merged my private DVFS dev repo into NeuSim. The future plan is to refactor the DVFS lookup table as part of the ChipConfig, so that the DVFS-related configs are not hardcoded inside a python module, and hopefully we can avoid this kind of "if" statement glues. But for now, please feel free to open a PR and apply your patch.