Repository navigation
perf(agc): run reads copy the missing blocks of a page mapped whole at once - #6471
Conversation
…t once ShaderMemory::readWords copied a run straight from its page only once every word of the page was valid. A page mapped whole fills its 16-word blocks on first use, so a run over a fresh page went through read() one word at a time: the initial-region lookup, the page lookup and a block test per word. Image-table columns are read this way on every capture. readWords now copies the run's missing blocks of such a page with one memcpy per run of blocks and serves the words from the page, marking them read and recent as before. The bytes, the blocks copied and the regions reported are those of the word-by-word path. Pages read word by word (pending GPU writes, partly mapped) and the initial regions keep that path. In 007 First Light's menu the capture walk takes 801 instead of 1,179 us per capture, and 132 instead of 495 us with the image-table column memo. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
|
Tested this head (726ef5f) on another title: Uncharted: Legacy of Thieves Collection (PPSA05684, #4001), Linux, RTX 4070 Ti SUPER, NVIDIA 615.78.08, i9-14900KF. Build: Scene: the orphanage (Chapter 2), heavy phase ~8 min after loading. Numbers are the
A profile of the driver threads before the change (
AI-assisted: yes |
|
Thanks @XairRrR for the second title and the A/B with this head as the only difference, and for dropping your local copy of the same change. Your numbers are added under Tested. AI-assisted: yes (Claude Code) |
What
ShaderMemory::readWordscopied a run straight from its page only once every word of the page was valid. A page mapped whole (lazy) fills its 16-word blocks on first use and starts empty in every draw (oneShaderMemoryper draw). So a run over it went throughread()one word at a time, each word paying for:std::prevon theinitialmap);Image-table columns are read this way on every capture.
readWordsnow copies the run's missing blocks of such a page with onememcpyper run of blocks. It then serves the words from the page and marks them read and recent, as the path for a fully valid page does.Before the change, in the scene under Tested (build A, which carries the column memo of #6440):
[capture]counted about 134k word reads per capture and a walk of 495 µs per capture. Of 6.15M pages fetched, 228 were read word by word.perf record -e cycles:u, 5 s),ShaderMemory::readtook 1,007 of 2,604 samples per frame,ShaderMemory::page133 andstd::_Rb_tree_decrement200.readunderreadWords←TableSnapshotter::Column.read21,page18,_Rb_tree_decrement0.Tested
Linux 7.2.10 (CachyOS), RTX 3080 with NVIDIA 615.78.08, Ryzen 9 7950X3D, GCC 16.2.1, Release.
ctest -R '^agc'onmain92e5041 with this change: 594 tests, 1 failure, 1 skip.agc_driver_store_over_untrackedatthe result did not reach a block the CPU left alone, the Linux failure that test(agc): keep waiting for the neighbour copy case's result #6385 fixes.agc_driver_stencil_ref_export.verifyImageTableBulkReadsgains a table placed inside 16-word blocks. ThroughShaderMemoryit must give the same snapshot as the word-by-word reader, and the captured regions must be exactly its records. There is no behaviour change for a test to observe, so the check guards the equivalence; it also passes withmain'sShaderMemorysources.main, so every build carries them; B and D add only this commit to A and C.readWordsas well.[capture]and[image-table]lines are from one extra pair per configuration withAPS5_PROFILE_DRAW=1.[capture]per capture: walk 494.6 → 131.9 µs, materialize 623.5 → 257.9 µs;[image-table]per 10 s: 9,166 → 15,809 snapshots, 5.88 → 2.53 s (0.64 → 0.16 ms each).Resources.Complete, which reads no shader memory), and the other queue workers waited 3.1-3.25 s on guest memory.Resources.Completeover 70 ms.[capture]per capture: walk 1178.5 → 801.1 µs, materialize 1309.6 → 936.2 µs;ShaderMemory::read956 → 24);[image-table]per 10 s: 5,179 → 6,807 snapshots, 7.66 → 7.01 s (1.48 → 1.03 ms each).APS5_TRACE_FRAMES=200:40, no other switches);Summary lines A1-A3, B1-B3, C1-C3, D1-D3
main2eb0c2b27 plus open PRs and local commits, with this head (726ef5f) the only difference between the two runs. Last 15[image-table]lines (150 s) ofAPS5_PROFILE_DRAW=1in a heavy scene, with the same workload in both runs (6,159 and 6,177 keys per snapshot):perf record -t, 25 s),ShaderMemory::readtook 6-13 % self time, underreadWords←TableSnapshotter::Narrow, with key buffers of up to 262,144 positions per scan (APS5_IMAGE_TABLE_KEY_SCAN=262144; the default is 256).ctest -R 'shader_memory|ShaderMemory|image_table'passes on that tree: perf(agc): run reads copy the missing blocks of a page mapped whole at once #6471 (comment)Related
initialfrom a map to a sorted vector in the same file, outsidereadWords. The two merge cleanly.readWordstoo. The two merge cleanly.Checklist
main; no other open PR implements the same functions.mdfiles or images added to the repository🤖 Generated with Claude Code