Skip to content

perf(memory): cache large pinned allocations in small_pinned_host_memory_resource - #185

Open
kevkrist wants to merge 3 commits into
NVIDIA:mainfrom
kevkrist:fix/pinned-large-alloc-cache
Open

perf(memory): cache large pinned allocations in small_pinned_host_memory_resource#185
kevkrist wants to merge 3 commits into
NVIDIA:mainfrom
kevkrist:fix/pinned-large-alloc-cache

Conversation

@kevkrist

Copy link
Copy Markdown

Summary

Requests above the 8 KB slab range currently pay a raw cudaHostAlloc/cudaFreeHost on every call. cuDF's parquet reader makes these allocations constantly, and the frees stall query execution — on a GB10 running TPC-H through Sirius, cudaFreeHost alone accounted for 0.65 s inside a 1.9 s query window.

This serves >8 KB requests from per-bucket (power-of-two) free lists with the same event-ordered reuse discipline the slab path already uses, capped at 256 MiB (constructor-tunable) with oldest-first eviction and purge-and-retry on allocation failure. Requests whose bucket exceeds the cap allocate at exact size and bypass the cache. Event pools are keyed per device so records always land on the owning context; when no event can be recorded, the large path frees instead of caching and the slab path synchronizes the freeing stream before recycling — the latter closes a pre-existing unordered-reuse window in the slab path.

Measured on TPC-H SF50 (Sirius, single GB10): pinned alloc/free pairs during query execution drop from 264 to 21 cold-start fills, and total hot runtime across the 22 queries improves by 13.9%.

Testing

  • cucascade_tests "[small_pinned]": 22 cases (10 new) covering bucket rounding, cache-hit reuse, cap accounting and eviction order, exact-size never-cacheable behavior, event ordering on a real stream, and destructor cleanup with a populated cache.
  • 22/22 TPC-H SF50 GPU-vs-CPU result validation through Sirius with this change applied.

…ory_resource

Requests above the slab range previously paid a raw cudaHostAlloc /
cudaFreeHost on every call; cuDF's parquet reader makes these
constantly and the frees stall query execution. Serve them instead from
per-bucket free lists with the same event-ordered reuse discipline as
the slab path, capped at 256 MiB (constructor-tunable) with oldest-first
eviction and purge-and-retry on allocation failure. Requests whose
bucket exceeds the cap allocate at exact size and bypass the cache.

Event pools are keyed per device so records always land on the owning
context; when no event can be recorded, the large path frees instead of
caching and the slab path synchronizes the freeing stream before
recycling, closing a pre-existing unordered-reuse window.
@copy-pr-bot

copy-pr-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@kevkrist

kevkrist commented Aug 15, 2026

Copy link
Copy Markdown
Author

Sirius TPC-H SF1000 performance (GB300)

Setting Base PR 185 Improvement
O_DIRECT, unpinned 150.41 s 146.94 s 2.30%
O_DIRECT + raw prefetch cache, unpinned 153.73 s 149.07 s 3.03%
Linux page cache, unpinned 59.70 s 52.55 s 11.98%
Compression-enabled host pinning: pin time 174.20 s 164.37 s 5.64%
Compression-enabled host pinning: warm query time 13.72 s 13.54 s 1.27%

Against Sirius's current cuCascade pin (416ba85), PR 185 improved the unpinned O_DIRECT workload by 2.32%. All query results matched byte-for-byte. Host-compression fallbacks were identical between arms.

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