Skip to content

The memory search has two passes, and remembers where a card's memory gave out - #38

Merged
Rovey merged 16 commits into
mainfrom
memory-median
Oct 11, 2026
Merged

Rovey merged 16 commits into
mainfrom
memory-median

Conversation

@Rovey

@Rovey Rovey commented Oct 11, 2026

Copy link
Copy Markdown
Owner

What

  • Two passes. The scan goes up and only has to find where it ends: a step that is not stable, or one more than 5 % below the best. Then the offset to keep is read again, starting four steps (200 MHz) below the highest step the scan passed and going down until a reading is more than 1 % below the best of them; the lowest offset within that 1 % is kept.
  • A single reading no longer decides. A reading that would end the scan is taken three times and the middle one counts, and the best that readings are held against is the highest middle of three steps in a row.
  • The edge is met once. A scan that ended in a wrong result or a reset event writes that offset to the journal, bound to the card and its driver version. A later scan on the same card and driver stops four steps below it and says so. With another driver or card the line does not count; builds that do not know the line skip it.
  • A bandwidth measurement that loses the device now says so; the log line ended in nothing.

Why

Four runs on one day saved a memory offset of +650, +1600, +550 and +100 MHz on the reference RTX 4070, a card that runs every game at +1500. That card has no bandwidth peak: bandwidth rises until the memory fails, so the scan could only end early by chance. The chance came from another program on the card (see #35). What is left for the search is to give a sound result also when the user goes on next to such a program, and not to go to the memory's edge in every run.

A detour that is not in here

A timed run four times as long was tried for steadier readings. It was no steadier on a quiet card, and with it five scans out of five lost the device at the memory's edge, once with the whole machine. It is gone; the bandwidth copy is the one the released versions use. The history is in docs/development.md and hardware check 95.

Tested

  • Unit tests on a simulated card with the reference card's numbers: the second pass never reads above the margin, in the first run and in the one after it, with readings scattering by 1.3 % in both passes and level changes thrown in, and with the edge anywhere from +300 to +2900. The tests fail when the margin is set to nothing. Suite and AddressSanitizer suite green.
  • On the reference card (hardware check 95 f), quiet, with the edge in its journal: the scan stopped at +2250, the second pass kept +2100, +1450 was applied, no reset, 3.1 % faster than stock.
  • Not seen with this search: a first scan on a card whose edge is not in the journal yet. It goes up with the same copy as the released versions.

Cost

A card that does have a bandwidth peak keeps an offset up to 200 MHz below it when the scan ends close above the peak.

🤖 Generated with Claude Code

Rovey and others added 16 commits October 11, 2026 19:32
…a 3 % drop

On the reference RTX 4070 four runs on one day saved a memory offset of
+650, +1600, +550 and +100 MHz. The card has no bandwidth peak before its
first wrong result, so the scan could only end early by chance.

Measured (hardware check 95), the readings move in three ways:
- one timed run of 75 ms was too short: readings scattered by 0.4 to 1.3 %
  and now and then did not settle. A run now copies four times as much
  (kBwDispatches 256) and the scatter is 0.2 %;
- a single reading decided a step. A step is now the median of three
  (kBandwidthReadings); a reading that only did not settle is left out
  when two others gave a number;
- for up to a minute at a time every reading sits about 1.8 % higher. The
  drop that ends the scan (kBandwidthDrop) goes from 1 % to 3 %.

The window's own drawing was suspected and measured: it adds nothing, so
nothing was built for it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…a driver reset

Two Best of my GPU runs in a row on the reference card applied a memory
offset of +1400 and +1450 and were 4 % faster than stock. Both scans ended
with the device lost during the bandwidth copy, at +2450 and +2500, where
the build before measured a number and the stress load reported the first
wrong result at +2550. Recorded as the open point that keeps the change
from being merged.

A bandwidth measurement that loses the device now says so; the log line
ended in nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Three readings at every step made the offset repeat on the reference card
(+1400 and +1450 in two runs), and ended both scans in a driver reset
during the bandwidth copy near the memory's edge (hardware check 95 b): a
step copied about seven times as much as before, and the copy checks
nothing.

A step is one reading again. Only a step that is more than kBandwidthTie
below the best is sampled kBandwidthReadings times, and its middle reading
counts; that replaces the single re-measure of a drop. A reading that only
did not settle is taken again. The longer timed run and the 3 % drop stay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…can that does not end in one

The same two runs with one reading a step applied +1400 and +1500, both
5 % faster than stock, and both scans again lost the device during the
bandwidth copy at +2500. So the reset does not come from reading a step
three times: four runs out of four with the longer timed run end this way.

docs/development.md gets the open point and a design that is not built:
the edge is found once and remembered in the journal, and the stress load,
which can report a wrong result, meets the edge before the copy does.

Two comments that named the ruled-out cause are corrected, and the error
text of a lost device reads as a sentence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… scans stay below it

On a card whose bandwidth rises until its memory fails, nothing ends the
memory scan before the edge, and on the reference card every scan ended
there in a driver reset (hardware check 95).

A memory scan that ended in a wrong result or a reset event now writes
the offset to the journal, bound to the card and its driver version. A
later run on the same card and driver stops its scan four steps below it
(kResetBackoffSteps, where confirming starts after a reset) and says so.
With another driver or another card the edge does not count.

The line has no id, so builds that do not know it skip it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…(e) have to show

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the machine restarted

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The long bandwidth copy lost the device at the memory's edge in five
scans out of five on the reference card, and the fifth time the machine
restarted (hardware check 95). The short copy got through there the one
time it was taken that far.

The search now has two passes. The scan goes up with the short copy and
only finds where it ends: a step that is not stable, or one more than 5 %
below the best, where the best is the highest middle of three steps in a
row and a reading that would end the scan is taken three times. Then the
long copy reads the offset to keep, starting four steps below the highest
step the scan passed and going down until a reading is more than 1 %
below the best of them.

A scan held below an edge the journal remembers counts that margin from
the edge, so the run after gives the same offset as the run that found it.

Tested on a simulated card with the reference card's numbers; not run on
a card.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ly source of the scatter

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…levels

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… use per program

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…econd it was closed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	docs/hardware-checks.md
#	tests/test_search.cpp
…s gone

The long bandwidth copy was added because the short one scattered. That
scatter came from another program on the card (hardware check 96): on a
quiet card the short copy is as steady, and main now looks for such
programs before a run. The long copy was also what lost the device at
the memory's edge in five scans out of five, once with the machine.

The two passes stay: the scan finds where it ends, and the offset is read
again from four steps below the highest step it passed. What makes the
result repeat is that structure, not a steadier reading. The remembered
edge and the coarser, single-reading-proof end of the scan stay as well.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nce card

One Best of my GPU run on a quiet card with the edge in its journal: the
scan stopped at +2250, the second pass kept +2100, +1450 was applied, no
reset, 3.1 % faster than stock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Rovey
Rovey merged commit 60826ea into main Oct 11, 2026
2 checks passed
@Rovey
Rovey deleted the memory-median branch October 11, 2026 21:59
@Rovey Rovey mentioned this pull request Oct 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant