Power, then heat: what limits the ET-SoC-1's matmul speed
Horace He found that an A100 runs the same matmul about 15% faster on zeros than on random numbers, because the GPU sits at its power cap: data that flips fewer transistors draws fewer watts and earns a higher clock. The ET-SoC-1's firmware has two caps, 65 W of card power and 65 °C on the die, so the same effect could come from either. This experiment pulls them apart on aifoundry2's card and reads every clock step's cause from the service processor's own log.
The answer
Both limits act, each on its own, and which one sets the speed depends on the die's temperature. On a die below 65 °C only the power test acts: every one of the 10 runs whose work drew 67 W or more at 800 MHz was stepped down by the power test first (PASS, rule R1), and none of the 10 runs under 62 W was (PASS, R2). Random normal data on the full card draws about 82 W at 800 MHz, so the governor pulls it back to a mean of 710 MHz, while zeros (35 W) and ones (50 W) stay at the 800 MHz ceiling: Horace's effect, by Horace's mechanism, 13% here against his 15%. On a die above 65 °C only the thermal test acts, even for zeros at a third of the power cap (PASS, R3). For sustained work on this card, heat wins: over 80 s the die settles where its cooling puts it, and on this card the 65 °C line sits at about 50 W of steady board power, below the 65 W level; 5 of the 5 sustained runs that left 800 MHz spent most of that time under the thermal test and 0 under the power test (PASS, R4); zeros ran at 800 MHz for the whole run at 59 °C and 36 W, held back by nothing but the clock table; so a sustained matmul runs 33% faster on zeros than on random data (12.3 against 9.2 fp32 TFLOPS): Horace's effect again, wider, and set by heat.
What was known before
The Horace experiment (September) ran this kernel at a fixed 600 MHz on a hot die and found the same arithmetic drawing 38.3 W on zeros, 46.7 W on ones and 63.4 W on random normal data. From a 62–63 °C die it saw the speed effect too: 11.4–11.8 TFLOPS on zeros against 9.3 on random data, about 25%. But the limits were tangled then. The card idled above 65 °C, random data at 800 MHz touched 88 W and took the die past 65 °C within half a second, and ones (56 W, under the power level) lost 800 MHz to the thermal test alone. Since 9 October a fan bracket keeps aifoundry2's idle die at about 50 °C. So the two limits can now be pulled apart without changing anything on the card.
What the specifications say
Esperanto presented the chip at Hot Chips 2021 as 1,088 RISC-V cores that typically draw under 20 W and
"can be adjusted for 10 to 60+ watts under SW control", with an operating range of 300 MHz to 2 GHz
(slides;
its energy-versus-voltage curve, by its own footnote 6, compares different physical designs, not one chip). The card in the
lab is narrower. Its operating-point table has three points, 600, 700 and 800 MHz at 0.517, 0.568 and 0.618 V, so
800 MHz is a hard ceiling. And its firmware (open source, thermal_pwr_mgmt.c in et-platform) has a software
governor with two limits that are set, not physical: a 65 °C threshold on the integer mean of 34 on-die
sensors, tested first, and a 65 W TDP level, plus a 75 W / 75 °C alarm in the power-management chip. A
step down when either is exceeded, a step up when neither is, no dead band.
So a matmul on this card can be held back three ways: by the clock table's top (800 MHz), by the power level, or by the temperature level. The runs below separate them.
On a cool die: the power limit alone
Ten fp32 operand patterns ran on all 1,024 minions, and random normal data on 768, 640 and 512, each for 6 s from a die reading of 55 °C or less, twice in shuffled order. The clock left 800 MHz exactly when the work crossed the power level, whatever made up the watts: random normal data on 768 minions (69 W) was stepped down, on 640 (62 W) it was not, and ones and random powers of 2 under 65 W ran at the ceiling with no power step at all.
The numbers
| operands | pass | W at 800 MHz | mean MHz after 1.5 s | TFLOPS, whole run | power steps down | die at start, °C | die max, °C |
|---|---|---|---|---|---|---|---|
| zeros | 1 | 35.0 | 800 | 12.14 | 0 | 55 | 57 |
| zeros | 2 | 35.1 | 800 | 12.09 | 0 | 56 | 57 |
| 75% zeros | 2 | 40.2 | 800 | 11.77 | 0 | 56 | 58 |
| 75% zeros | 1 | 40.2 | 800 | 12.11 | 0 | 56 | 58 |
| ones | 1 | 49.0 | 800 | 12.15 | 0 | 50 | 55 |
| ones | 2 | 51.3 | 800 | 11.81 | 0 | 56 | 60 |
| random normal, 512 minions | 2 | 55.8 | 800 | 5.95 | 0 | 56 | 61 |
| random normal, 512 minions | 1 | 55.9 | 800 | 5.82 | 0 | 56 | 61 |
| random signs ±1 | 1 | 59.3 | 800 | 12.02 | 0 | 54 | 60 |
| random signs ±1 | 2 | 60.7 | 800 | 11.69 | 0 | 56 | 62 |
| random powers of 2 | 2 | 62.4 | 800 | 12.02 | 0 | 56 | 62 |
| random normal, 640 minions | 2 | 62.4 | 800 | 7.44 | 0 | 56 | 62 |
| random powers of 2 | 1 | 62.5 | 800 | 12.05 | 0 | 56 | 62 |
| random normal, 640 minions | 1 | 62.6 | 800 | 7.30 | 0 | 56 | 62 |
| A random, B ones | 1 | 65.2 | 785 | 11.90 | 3 | 55 | 62 |
| A random, B ones | 2 | 65.7 | 784 | 11.70 | 3 | 56 | 63 |
| random normal, 768 minions | 2 | 69.0 | 776 | 8.73 | 7 | 56 | 63 |
| random normal, 768 minions | 1 | 69.2 | 772 | 8.49 | 6 | 56 | 62 |
| A ones, B random | 1 | 72.7 | 740 | 11.24 | 9 | 56 | 63 |
| A ones, B random | 2 | 72.8 | 742 | 11.18 | 9 | 56 | 63 |
| random mantissas | 2 | 77.8 | 722 | 10.76 | 10 | 56 | 63 |
| random mantissas | 1 | 78.1 | 728 | 10.73 | 10 | 56 | 63 |
| uniform [0,1) | 1 | 78.8 | 716 | 10.87 | 11 | 55 | 62 |
| uniform [0,1) | 2 | 79.5 | 706 | 10.85 | 10 | 56 | 63 |
| random normal | 1 | 81.0 | 706 | 10.76 | 10 | 52 | 59 |
| random normal | 2 | 83.5 | 714 | 10.46 | 10 | 56 | 63 |
The mechanism is a dither. Once a ~1.3 s average of the card's power passes 65 W the governor steps down one point per pass (about 0.24 s), and once it falls under, steps up again, with nothing in between to stop it. For random normal data the card goes 800 → 700 → 600 → 700 → 800, round and round, drawing about 83, 65 and 50 W at the three points, and the average sits on the level. The governor logged its power reading at each of 98 power steps down: 65.01 to 67.85 W, while the board's own reading at 800 MHz was 82 W. A model of that loop, a first-order average with a 1.3 s time constant compared against 65 W once per pass, reproduces the mean clock of all 26 cool-die runs to 3.3 MHz rms.
The numbers
| operands | W at 800 MHz | mean MHz | TFLOPS | power steps down | die at start, °C | die max, °C |
|---|---|---|---|---|---|---|
| zeros | 35.0 | 794 | 12.14 | 0 | 55 | 57 |
| A random, B ones | 65.2 | 782 | 11.90 | 3 | 55 | 62 |
| random normal | 81.0 | 713 | 10.76 | 10 | 52 | 59 |
On a hot die: the temperature limit alone
Work that draws less than 65 W even at 800 MHz, ones and zeros, was launched on a die heated to 63–67 °C. The log of those 12 runs holds 55 thermal steps, every one at a reading of 66 °C, and 0 power steps. Runs that started above the line held 600 MHz until the die read 65 °C (4 of 4), then climbed, heated, and were sent back down; every run that reached 66 °C at 800 MHz was stepped down by the thermal test and not the power test (4 of 4). Zeros, at about a third of the power level, lost speed to heat alone.
The numbers
| step | count | die min, °C | die max, °C | power min, W | power max, W |
|---|---|---|---|---|---|
| power step down | 98 | 57 | 63 | 65.01 | 67.85 |
| power step up | 295 | 50 | 66 | 23.59 | 64.96 |
| thermal step down | 104 | 66 | 67 | 36.00 | 61.00 |
Sustained: which limit holds a long matmul
Each number type ran for about 80 s: nine 8 s launch processes back to back from a die of 57 °C or less. A run whose power at 800 MHz is over the level starts in the power dither, but the die keeps warming, and once it reads 66 °C the thermal test takes over: fp32 random data first read 66 °C 8 s in, fp32 ones, under the power level, 28 s in. From then on the thermal test sets the clock. For random fp32 and fp16 data it holds 600 MHz, the bottom of the table, and the die stays above the line anyway (67 °C): the governor has no lower step to take. Only work light enough to keep the die under 65 °C for good holds the ceiling.
- fp32 random normal: 600 MHz in the last 40 s, 0% of it at 800 MHz, the rest 100% thermal and 0% power; die 67.1 °C, board 54.4 W
- fp16 random normal: 600 MHz in the last 40 s, 0% of it at 800 MHz, the rest 100% thermal and 0% power; die 66.1 °C, board 51.3 W
- int8 random (uniform over −128 to 127): 763 MHz in the last 40 s, 66% of it at 800 MHz, the rest 100% thermal and 0% power; die 65.3 °C, board 50.7 W
- fp32 ones: 738 MHz in the last 40 s, 48% of it at 800 MHz, the rest 100% thermal and 0% power; die 65.4 °C, board 49.4 W
- fp16 ones: 737 MHz in the last 40 s, 48% of it at 800 MHz, the rest 100% thermal and 0% power; die 65.4 °C, board 49.3 W
- int8 ones: 800 MHz in the last 40 s, 100% of it at 800 MHz; die 61.7 °C, board 41.8 W
- fp32 zeros: 800 MHz in the last 40 s, 100% of it at 800 MHz; die 59.0 °C, board 36.4 W
- fp16 zeros: 794 MHz in the last 40 s, 97% of it at 800 MHz, the rest 0% thermal and 0% power; die 59.0 °C, board 36.1 W
- int8 zeros: 800 MHz in the last 40 s, 100% of it at 800 MHz; die 59.0 °C, board 37.6 W
The line through the nine runs' last 40 s gives the cooling: the die reading rises 0.47 °C per watt of board power, and reads 65.5 °C at 50 W. That is the sustained power the 65 °C test allows here, and it is below the 65 W level: on aifoundry2's cooling the temperature limit is the tighter of the two for anything that runs long.
The numbers
| type | operands | mean MHz, last 40 s | TFLOPS or TOPS, last 40 s (kernel) | with the gaps between launches | die °C | board W | share at 800 MHz | below 800: thermal | below 800: power |
|---|---|---|---|---|---|---|---|---|---|
| fp16 | ones | 737 | 22.25 | 21.68 | 65.4 | 49.3 | 0.48 | 0.52 | 0.00 |
| fp16 | randn | 600 | 18.43 | 17.81 | 66.1 | 51.3 | 0.00 | 1.00 | 0.00 |
| fp16 | zeros | 794 | 24.37 | 23.73 | 59.0 | 36.1 | 0.97 | 0.00 | 0.00 |
| fp32 | ones | 738 | 11.12 | 10.81 | 65.4 | 49.4 | 0.48 | 0.52 | 0.00 |
| fp32 | randn | 600 | 9.21 | 8.90 | 67.1 | 54.4 | 0.00 | 1.00 | 0.00 |
| fp32 | zeros | 800 | 12.28 | 11.96 | 59.0 | 36.4 | 1.00 | 0.00 | 0.00 |
| int8 | ones | 800 | 84.33 | 81.66 | 61.7 | 41.8 | 1.00 | 0.00 | 0.00 |
| int8 | randn | 763 | 79.48 | 77.11 | 65.3 | 50.7 | 0.66 | 0.34 | 0.00 |
| int8 | zeros | 800 | 84.32 | 82.20 | 59.0 | 37.6 | 1.00 | 0.00 | 0.00 |
What speed to expect, by number type
fp32 and fp16 matmuls retire one 16×16 tile operation every 546 cycles and int8 every 318, so at the 800 MHz ceiling the full card does 12.3 fp32 TFLOPS, 24.6 fp16 TFLOPS and 84.4 int8 TOPS. What it actually delivers depends on the data and on how long it has been running:
| type | data | at 800 MHz | cool die, first 8 s | sustained, last 40 s | MHz, last 40 s | die °C | board W | % of below-800 time thermal |
|---|---|---|---|---|---|---|---|---|
| fp32 | zeros | 12.3 | 12.3 | 12.3 | 800 | 59.0 | 36.4 | – |
| fp32 | ones | 12.3 | 12.3 | 11.1 | 738 | 65.4 | 49.4 | 100 |
| fp32 | random normal | 12.3 | 10.7 | 9.2 | 600 | 67.1 | 54.4 | 100 |
| fp16 | zeros | 24.6 | 24.6 | 24.4 | 794 | 59.0 | 36.1 | 0 |
| fp16 | ones | 24.6 | 24.6 | 22.3 | 737 | 65.4 | 49.3 | 100 |
| fp16 | random normal | 24.6 | 22.0 | 18.4 | 600 | 66.1 | 51.3 | 100 |
| int8 | zeros | 84.4 | 84.4 | 84.3 | 800 | 59.0 | 37.6 | – |
| int8 | ones | 84.4 | 84.4 | 84.3 | 800 | 61.7 | 41.8 | – |
| int8 | random (uniform −128..127) | 84.4 | 84.4 | 79.5 | 763 | 65.3 | 50.7 | 100 |
The numbers
| type | operands | unit | at 800 MHz | cool die | sustained | sustained ÷ cool |
|---|---|---|---|---|---|---|
| fp32 | zeros | TFLOPS | 12.3 | 12.29 | 12.28 | 0.999 |
| fp32 | ones | TFLOPS | 12.3 | 12.29 | 11.12 | 0.904 |
| fp32 | randn | TFLOPS | 12.3 | 10.73 | 9.21 | 0.858 |
| fp16 | zeros | TFLOPS | 24.6 | 24.58 | 24.37 | 0.992 |
| fp16 | ones | TFLOPS | 24.6 | 24.58 | 22.25 | 0.905 |
| fp16 | randn | TFLOPS | 24.6 | 22.03 | 18.43 | 0.837 |
| int8 | zeros | TOPS | 84.4 | 84.41 | 84.32 | 0.999 |
| int8 | ones | TOPS | 84.4 | 84.41 | 84.33 | 0.999 |
| int8 | randn | TOPS | 84.4 | 84.41 | 79.48 | 0.942 |
Under other power levels the governor model gives the speed each kind of number would hold on a cool die, from that kind's own measured power at 600, 700 and 800 MHz (a model: the level was not changed on the card):
| type | data | W at 800 MHz | 35 W level | 45 W level | 55 W level | 65 W level | 75 W level | 85 W level |
|---|---|---|---|---|---|---|---|---|
| fp32 | zeros | 36 | 11.9 | 12.3 | 12.3 | 12.3 | 12.3 | 12.3 |
| fp32 | ones | 52 | 9.2 | 11.0 | 12.3 | 12.3 | 12.3 | 12.3 |
| fp32 | random signs | 61 | 9.2 | 10.2 | 11.6 | 12.3 | 12.3 | 12.3 |
| fp32 | A ones, B random | 73 | 9.2 | 9.2 | 10.5 | 11.6 | 12.3 | 12.3 |
| fp32 | random normal | 83 | 9.2 | 9.2 | 9.8 | 10.8 | 11.6 | 12.3 |
| fp16 | zeros | 36 | 23.9 | 24.6 | 24.6 | 24.6 | 24.6 | 24.6 |
| fp16 | ones | 52 | 18.7 | 22.2 | 24.6 | 24.6 | 24.6 | 24.6 |
| fp16 | random normal | 78 | 18.4 | 18.4 | 20.1 | 22.0 | 23.7 | 24.6 |
| int8 | zeros | 37 | 79.9 | 84.4 | 84.4 | 84.4 | 84.4 | 84.4 |
| int8 | ones | 40 | 79.0 | 84.4 | 84.4 | 84.4 | 84.4 | 84.4 |
| int8 | random (uniform −128..127) | 51 | 64.3 | 77.4 | 84.4 | 84.4 | 84.4 | 84.4 |
TFLOPS for fp32 and fp16, TOPS for int8, on all 1,024 minions, from the modelled mean clock after the start ramp.
The surface
Put the two axes together: the work's power at 800 MHz (the data: zeros at the left, random normal data at the right) and the power level the governor is given. The fitted governor model gives the mean clock for every pair. Under the card's 65 W the measured runs fall on the model's row. Every 10 W of extra level buys random fp32 data about 60 MHz of mean clock until it reaches the 800 MHz ceiling near 85 W, and on this card the 65 °C threshold sets a lower effective level for sustained work (about 50 W, the amber line). This part is a model: the level itself was never changed (the lab's rule: no TDP, threshold or clock is set on a shared card).
The numbers
| cap W \ data W | 34 | 43 | 53 | 62 | 72 | 81 | 91 |
|---|---|---|---|---|---|---|---|
| 30 | 724 | 600 | 600 | 600 | 600 | 600 | 600 |
| 40 | 800 | 758 | 667 | 600 | 600 | 600 | 600 |
| 50 | 800 | 800 | 770 | 697 | 642 | 600 | 600 |
| 60 | 800 | 800 | 800 | 776 | 715 | 676 | 633 |
| 70 | 800 | 800 | 800 | 800 | 785 | 727 | 691 |
| 80 | 800 | 800 | 800 | 800 | 800 | 788 | 752 |
| 90 | 800 | 800 | 800 | 800 | 800 | 800 | 791 |
How it was run
- Pre-registered before the first card pass: design, predictions and rules R1–R4 in the README. Amendments: A0, a use-count check that read the runner's own sampler as another user; A1, the trace reader (the lab's earlier one stopped at the first binary record and lost most governor lines); A2, the hot starts (the heater cannot take this card's die past about 67 °C, because the two limits hold it there); A3, the placement of the log's lines on the host clock (the ring keeps only its last ~67 entries, so a dump covers a short run's last few seconds and a sustained run's last 5–60 s, and is anchored at the run's end).
- Nothing was set on the card. The TDP and threshold read 65 W and 65 °C after every run.
- The cause of each step comes from the service processor's 4 KB trace ring, dumped after every run: its CRITICAL lines ("Power throttle down event, current pwr … tdp level …", "Thermal throttle down event, current temperature …"), its "New OP" line at every operating point set, and a 16-byte power-status record (power, throttle state, temperature, target clock), placed on the host clock by matching the operating-point lines to the sampler's clock changes. The ring holds about 67 entries, three per clock step, so the counts above are of the steps it kept; where it had wrapped, the sampler's die readings still say which side of 65 °C each step was on.
- The kernel is the Horace experiment's: one 16×16 TensorFMA per minion on tiles in its L1 scratchpad, back to back. Speeds come from the kernel's own cycle counters.
- Claimed and released in #community-lab; 47 runs, about 32 minutes of card time.