Skip to content

Commit 18ee742

Browse files
authored
Merge pull request #34 from Rovey/readme-all-in-one
docs: the README's All in one numbers, and why the memory offset differs from run to run
2 parents 44fb60e + 07fc794 commit 18ee742

4 files changed

Lines changed: 23 additions & 22 deletions

File tree

‎README.md‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
[**Download**](https://github.com/Rovey/gpu-auto-optimizer/releases/latest) · [What one click does](#one-click-then-nothing) · [How it works](#how-it-works) · [Command line](#command-line) · [FAQ](#faq)
1616

17-
<img src="docs/images/hero.svg" width="860" alt="One click on the reference RTX 4070: 1.6 % more speed on 8 % less power, with the fans at 62 % instead of 73 %. Best of my GPU alone: 4.5 % more speed. Undervolt alone: 20 % less power, 8 °C cooler.">
17+
<img src="docs/images/hero.svg" width="860" alt="One click on the reference RTX 4070: 0.8 % more speed on 10 % less power, with the fans at 52 % instead of 70 %. Best of my GPU alone: 4.5 % more speed. Undervolt alone: 20 % less power, 8 °C cooler.">
1818

1919
<img src="docs/images/dashboard.png" width="860" alt="The GPU Auto Optimizer dashboard: live telemetry, the current tuning, the profiles and the log">
2020

@@ -46,22 +46,22 @@ What else is in it:
4646

4747
<div align="center">
4848

49-
<img src="docs/images/all-in-one-result.png" width="860" alt="The result screen of an All in one run on the reference RTX 4070: core +135 MHz, memory +1500 MHz, power limit 105 %, 2850 MHz at 1035 mV, fans 52 % at 70 °C; score 5728 to 5820 iterations per second, power 196 to 180 watts, fan speed 73 to 62 percent">
49+
<img src="docs/images/all-in-one-result.png" width="860" alt="The result screen of an earlier All in one run on the reference RTX 4070: core +135 MHz, memory +1500 MHz, power limit 105 %, 2850 MHz at 1035 mV, fans 52 % at 70 °C; score 5728 to 5820 iterations per second, power 196 to 180 watts, fan speed 73 to 62 percent">
5050

5151
</div>
5252

53-
**All in one** is the default: it overclocks, undervolts on top of that, measures the quietest fan curve and tests the whole for five minutes. One run on the reference card, both columns five minutes of full load:
53+
**All in one** is the default: it overclocks, undervolts on top of that, measures the quietest fan curve and tests the whole for five minutes. One run on the reference card, both columns five minutes of full load (the picture above is of an earlier run and shows that run's numbers):
5454

5555
| | Stock | After one click |
5656
|---|---|---|
57-
| Stress-test score | 5728 it/s | **5820 it/s (+1.6 %)** |
58-
| Power under load | 196 W | **180 W (−8.2 %)** |
59-
| Fan speed | 73 % | **62 %** |
60-
| Temperature | 67 °C | 71 °C |
61-
| Core clock under load | 2789 MHz | 2835 MHz |
62-
| Memory clock under load | 10495 MHz | 12000 MHz |
57+
| Stress-test score | 5309 it/s | **5353 it/s (+0.8 %)** |
58+
| Power under load | 185 W | **166 W (−10.3 %)** |
59+
| Fan speed | 70 % | **52 %** |
60+
| Temperature | 66 °C | 70 °C |
61+
| Core clock under load | 2787 MHz | 2835 MHz |
62+
| Memory clock under load | 10474 MHz | 11051 MHz |
6363

64-
A little faster, on less power, with slower fans. The card is warmer because the fans are allowed to be: the fan tune aims for 70 °C, 5 °C under the profile's limit, and found that 52 % holds it. With the NVIDIA driver's own fan curve the same settings ran at 63 °C on 176 W. The run took 34 minutes. A second run gave 0.9 % more score on 10.8 % less power, with the fans at 55 %.
64+
As fast or a little faster, on a tenth less power, with much slower fans. The card is warmer because the fans are allowed to be: the fan tune aims for 70 °C, 5 °C under the profile's limit, and found that 52 % holds it. Before the fan tune, with the fans on the profile's own curve, the same settings ran at 66 °C on 163 W. The run took 31 minutes. Two earlier runs gave 1.6 % more score on 8.2 % less power with the fans at 62 %, and 0.9 % more on 10.8 % less with the fans at 55 %. How much memory offset a run finds differs from run to run on this card (+550 in this one, +1500 in the first of those); the score barely moves with it.
6565

6666
The gains are smaller than those of the two sections below, and that is the point of it. An overclock and an undervolt do not add up: an overclock moves the whole voltage/frequency curve, so at every clock the card already runs on less voltage, and with the same safety margin there is nothing left to take off. They are two ends of one line. All in one takes the middle, where the card beats stock on both counts; **Best of my GPU** and **Undervolt** are the ends.
6767

@@ -70,7 +70,7 @@ The gains are smaller than those of the two sections below, and that is the poin
7070
</div>
7171

7272
> [!NOTE]
73-
> Close games and other programs that use the graphics card before a run. In an earlier run an emulator on 11 % of the card cost 6 % of the score; the run now says so when its final test does not match the step before it. The logs are in [docs/hardware-checks.md](docs/hardware-checks.md) (checks 75 and 76).
73+
> Close games and other programs that use the graphics card before a run. In an earlier run an emulator on 11 % of the card cost 6 % of the score; the run now says so when its final test does not match the step before it. The logs are in [docs/hardware-checks.md](docs/hardware-checks.md) (checks 75, 76 and 94).
7474
7575
## All of the speed instead: +4.5 % performance
7676

‎docs/development.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ The applied offset is always at least one step below the confirmed edge. Profile
7979
| Without the bandwidth measurement the memory is left at stock | The search used to fall back to a climb on stability alone when the measurement failed at +0. On a tester's 3080 Ti (0.4.3) that climb went to +2300 MHz with the score falling from +2150 on, got its first wrong result there, and the machine froze with a corrupted screen in the 30 s confirm probes just below it. The first wrong result is no edge to stand next to: the memory was correcting errors for hundreds of MHz before it. Now a measurement that does not work means no memory overclock (`left_at_stock`), the run says so, and the core is still searched. `optimize` keeps the stability climb only for a caller that gives no measurement at all; the app always gives one. Why the measurement failed on that card is not known: the log was only in the window and went with the reboot. |
8080
| A confirm probe that is too hot at once confirms nothing | A confirm probe that ends `TOO HOT` keeps the clock edge: over 30 s the card may run a little hotter than over the power step's 20 s, and that is the soak's business, which lowers power. But the stress run stops at its first reading above the limit, so a card that is above it when the probe begins gives `TOO HOT` within a second, and that counted as holding too. It happened on the tester's RTX 3080 Ti (hardware check 91): after a driver reset the health probe loads the card at stock power, which on that card means 76 C against a limit of 75, and `confirm core +225` was confirmed by a probe that had tested nothing. Now such a probe counts only when the clock was loaded for `kConfirmMinS` (10 s, clearly longer than the 3 s probe that found the edge) before it got too hot. Otherwise the value is not confirmed, and the card rests (`io.rest`, the 20 s of a recovery, with the fans where the curve last put them) before the next try one step lower: without the rest every lower value would start just as hot, and heat alone would step the edge down to nothing, which is what keeping the edge on `TOO HOT` was for. The same value is not tried again; one step is the price. Not changed: the health probe still runs at stock power, and a soak that begins too hot still lowers the power limit by a step. |
8181
| A profile that promises speed keeps no result that is slower than stock | Best of my GPU ended 3.8 % slower than stock on the tester's RTX 3080 Ti (4749 against 4937 it/s, hardware check 91), with the fans at 80 % instead of 66 %, and showed it as **Done**, applied and kept at every logon. Every step had done what it is for: the card runs 83 C at stock with its fans at 100 %, the profile allows 75, so the power limit went to 65 %, and +150 MHz of core clock did not win that back. But a profile called "the best of my GPU" that leaves the card slower has not done what it says, and a result like that is not offered as one. After the soak, `optimize` compares its score with the measurement at stock that went before the run (the "before" the result screen shows, so the rule judges by the number the user sees): below `kNotSlowerScore` (0.99: one percent is what two five-minute runs differ by) the run ends as a failed one does, at stock, with nothing saved, and says what it found, why, and that Undervolt is the profile for a card that runs warm. `Objectives::faster_than_stock` marks the two profiles this holds for, Best of my GPU and Max performance. Not Quiet and Cool & efficient, which trade speed for noise and heat and say so. Not the overclock step of All in one either: it goes on to an undervolt and a fan tune, and its result is judged as a whole; whether that whole may be slower than stock is not decided. This is a backstop, not the cure: what such a card needs from these profiles is in `docs/planned.md` ("never hotter than at stock"). |
82+
| Open: on the reference card the memory offset is decided by noise | Three runs on one day applied +650, +1600 and +550 (hardware check 94). The memory search assumes that bandwidth peaks before the memory makes errors (`kBandwidthDrop`: stop at a reading 1 % below the best, re-measured once). On the reference RTX 4070 it does not: bandwidth rises by about 0.4 % per 50 MHz step all the way to +2500, and the first wrong result comes at +2550. The readings scatter by 0.4 to 0.7 % (standard deviation), so two readings in a row 1 % under a high one happen by chance, and where that happens is where the scan ends: at +1000 twice, not at all once. When it does not happen the search stands next to the first wrong result after all, which is what the bandwidth method exists to avoid; the tie rule and the margin still put the applied offset 950 MHz below it. Nothing is changed yet. What a fix has to decide: whether a card like this should get a memory overclock by another rule (a fixed share of the range the scan covered, or of the offset of the first error), and how a real peak is told from scatter on the cards that have one (several readings per step and their median, or a drop that holds over more than one step). |
8283
| Open: why the bandwidth measurement fails on some cards, and what then | On the tester's RTX 3080 Ti it failed at +0, and since 0.4.4 that means no memory overclock at all on such a card, though it computed right far beyond +2000 MHz. The measurement gives a number only when three runs in a row agree within 1 % (`kBwSettle`), and it throws away every run the driver's timer calls disjoint (the clock changed under it). That card was held at a power limit of 65 % and ran at 83 C when it was measured; the reference card has only ever been measured at 105 %, where the measurement itself draws 179 of 210 W. So the suspicion is the power limit, and hardware check 90 tests exactly that on the reference card. What it shows decides what is built, and nothing is built before it: **(1) runs are thrown away as disjoint, and the ones that are kept agree:** the timer is what fails, not the card. Time the copy differently (wall clock around a flush, or count a disjoint run when its neighbours agree) and keep the method. **(2) the readings themselves scatter by more than 1 %:** a peak that is found by a 1 % drop (`kBandwidthDrop`) cannot be found in that noise. Then the memory has to be measured where the card is not held back: search it before the power step, at stock power, where a probe and its measurement last five seconds; or take more readings and compare medians. **(3) it does not fail at 65 % on the reference card:** the power limit is not the cause. Then it was the heat (a card throttling at its temperature limit changes clock as well), or another program, and only the tester's `run.log` can say: since this change a measurement that never settled writes how many runs gave a reading, between which values, and how many were thrown away. In no case does the climb on stability alone come back. **Outcome of check 90: (3).** On the reference card the measurement gave a number fifteen times out of fifteen at 100, 80 and 65 %, in three or four runs, with nothing thrown away, and the bandwidth was the same at every limit. The power limit is ruled out; (1) and (2) are not built. What is left is the heat of that card, another program, or a timer query that failed, and the tester's `run.log` is the next thing that can tell them apart. **The tester's run (check 91): it is (2), but only inside a run.** Twenty readings between 763.9 and 821.2 GB/s, none thrown away, three seconds after the load began; after thirty seconds of load the same card read within 0.2 %. The suspicion now is the moment, not the card: the measurement is taken while the power limiter is still catching up. If `gao --bandwidth --after-load 3` scatters on that card and `--after-load 30` does not, that is it, and the fix is to measure when the card has settled (keep taking runs for some seconds instead of twenty runs), not to change the method. |
8384
| Every line of a run is also in `run.log` | `logged()` wraps the log hook of both front ends: a line is appended and flushed before it is shown, so the step a machine freezes in is the last line on disk. One file in the state folder, moved aside at 1 MB (`run.log.old`). Only elevated and only after `ensure_app_dir` has verified the folder: an elevated process appends to nothing a user could have put there. |
8485
| A run does not start while the NVIDIA app's Automatic Tuning is on | Switched on, a service of the driver scans the card when it sees fit: it loads it, changes its clocks, and starts again by itself (hardware check 89: a scan that was stopped started again 14 ms later, and after a restart of the service it resumed within two seconds). A run next to that measures nothing it can trust, so it is refused, like a run next to Afterburner, and with the same weight: a courtesy, not a guard. Read from where that service keeps the switch, `%ProgramData%\NVIDIA Corporation\nvtopps\nvtopps.db3`, table `ocScannerSettings`, fields `backgroundScanEnabled` and `grdOcEnabled`, joined to `TelemetryGpuCfg` so that only a card that is in the PC counts (a row of an earlier card can never be switched off again). That this is the source and not a copy of it was measured, not assumed: with the field set the service took the scan up again after every restart, with it cleared it did not, while the NVIDIA app itself showed the switch as off. Nothing documents the file. So: opened read-only and immutable (no lock, the service never waits for us), through `winsqlite3.dll` from System32 (no dependency added), and everything that is not exactly as expected reads as "unknown", which starts the run as before. The registry value the app sets next to it (`HKLM\SOFTWARE\NVIDIA Corporation\Global\NvApp\OC\<user SID>`) changes at the same moment but belongs to the app, not to the service, and is not used. **The overlay is not checked:** no setting for it was found, its processes run whether it is open or not, and the one value that moved (`IsShadowPlayEnabled`) followed the service being up, not a switch. NVAPI was not tried: an undocumented call is no better than an undocumented file, and it cannot be compared with anything. |

0 commit comments

Comments
 (0)