Repository navigation
[KV Offload][FS] Opt-in per-block CRC32C checksums - #57912
CHIPMUNK-T0T wants to merge 5 commits into
Conversation
|
Documentation preview: https://vllm--57912.org.readthedocs.build/en/57912/ |
|
@varun-sundar-rabindranath On the IOPS question from #54363: I measured the xattr implementation in this PR on ext4 / NVMe (i7-14700F, No additional device I/O per block on this setup. Reads/block were identical with checksums off/on, and writes/block differed only by noise (e.g. 32.35 vs 32.39 at 4 MiB), measured from At the tier's default concurrency (16 threads), 4 GiB per pass, median of 5:
So on this local ext4 setup, the xattr does not add observable device I/O and checksum mode does not materially reduce throughput at default concurrency. A filesystem that stores xattrs externally, or a network filesystem, may behave differently. |
|
Hi @CHIPMUNK-T0T , thank you for running the performance numbers. QQ : Can you also share the time it takes for the thread-pool to finish the workload with checksum on/off. Given that the CRC calculation expands the store / load time by 65%, is this reflected in the thread-pool e2e time ? Just want to understand where this time is absorbed. Also, it'd be nice to add a file-size vs crc32-comupation-time table. Thanks 🙌 |
|
I re-measured through For the same 4 GiB workload as my earlier table (4 MiB blocks × 64 jobs), the pool finished in 716.5 → 717.2 ms for store and 603.5 → 607.1 ms for load. With several jobs in flight, the pool e2e time does not show a consistent regression from checksumming, while process CPU time increases by about 1.4–3.0x. This is consistent with I/O becoming the limiting factor at higher concurrency, with CRC work overlapping with I/O across pool threads. With only one job in flight, that overlap is not available at the job level: one pool task processes its blocks serially, so the checksum cost is directly visible in job latency. At 1 MiB and above, I measured roughly +34–89%. So the checksum cost is reflected in single-job latency, but not in pool e2e time when several jobs are in flight; there it is absorbed as additional CPU time on the pool threads. Thread-pool e2e time, checksum off → on
Medians of 10 runs. The short one-job measurements have relatively high run-to-run variance, and 16 MiB store times also vary with the SSD's write state. Device reads/writes per block were effectively unchanged between checksum off/on in every row. Block size vs CRC32C computation time
Both columns run the CRC32C code from Thanks! |
0132ee7 to
000f561
Compare
|
Thanks @CHIPMUNK-T0T . I made a pass the PR generally looks good to me. Left a few high level comments. cc @zdtsw @Srinivasoo7 @dannyharnik PTAL 🙌 |
Hi @CHIPMUNK-T0T thanks for the PR. LGTM! |
|
This pull request has merge conflicts that must be resolved before it can be |
aed1b73 to
1306e76
Compare
|
@Srinivasoo7 |
Signed-off-by: Chipmunk <101038159+CHIPMUNK-T0T@users.noreply.github.com>
Signed-off-by: Chipmunk <101038159+CHIPMUNK-T0T@users.noreply.github.com>
… them Signed-off-by: Chipmunk <101038159+CHIPMUNK-T0T@users.noreply.github.com>
Signed-off-by: Chipmunk <101038159+CHIPMUNK-T0T@users.noreply.github.com>
…troactively Signed-off-by: Chipmunk <101038159+CHIPMUNK-T0T@users.noreply.github.com>
1306e76 to
b44ef8c
Compare
|
This pull request has merge conflicts that must be resolved before it can be |
Purpose
Implements item 1 of #54363. The FS tier catches a truncated block (short read) but not one whose bytes changed at the same size, e.g. bit rot; such a block is loaded as KV silently.
New tier option
checksum_blocks(defaultfalse), using the xattr approach preferred in the #54363 discussion:Store: the block's CRC32C is set as xattr
user.vllm.kv_crc32con the temp file, before the rename.Load: verified after the read. A checksum verification failure removes the file and fails the load with
EBADMSGthrough the existingnum_succeededpartial-keep path, withchecksum_failedset on the exception. The tier reports it asJobResult.checksum_failed, andTieringMetricsTrackercounts it invllm:kv_offload_tiering_checksum_failuresunder the indexed tier label (e.g.1:fs). AnEBADMSGfrom the filesystem itself (as ext4/xfs report metadata checksum errors) is not flagged, so it fails the load without removing the file or being counted.Backward compatible: a block with no recorded checksum still loads, so the option can be enabled on an existing cache. For the same reason
FileMapper.fieldsis not bumped, unlike the RFC text: the file contents do not change, so there is no cold start.xattrs unavailable at
root_dir: the tier fails at startup (see the design decision below).Implemented in both
csrc/fs_io.cpp(SSE4.2, table fallback) and the Python fallback infs/io.py. With the option off, no CRC or xattr call is made and the metric is not registered.batch_store_block/batch_load_blockinfs_io_Cgain a trailingchecksumargument, so the extension must be rebuilt with this change.Limitation: hardware CRC32C is x86-64 only. Other architectures, including ARM, use the table implementation (same value, slower); ARM hardware CRC can follow separately.
No other open PR references #54363, and searches for
checksum kv offload,crc32candxattrfind none in this area.Design decision to confirm
#54363 did not settle what checksum mode should do when xattrs are unavailable: fail, or disable itself with a warning. I chose to fail at startup, because a silent fallback hides that blocks are no longer verified. Is that acceptable?
Test Plan
New tests in
test_fs_tier.py, on both I/O paths where applicable: same recorded value on both paths, C and Python CRC32C agree for 1-12 bytes (C 8-byte words and byte tail), corrupt data / a short, long or wrong-value record, legacy block still loads, xattr set before the rename, startup failure without xattrs, metric registered only when enabled, a filesystemEBADMSGis not counted as a checksum failure. Intest_metrics.py, the tracker counts a checksum failure under the indexed tier label.Test Result
tests/v1/kv_offload/: 805 passed, 2 skipped (test_fs_tier.py: 74 passed, 29 new).Cost when enabled
i7-14700F, ext4 on NVMe,
O_DIRECT,fs_io_C, one thread, median per block:Device I/O counts are effectively unchanged in this ext4/NVMe setup (the 4-byte value lives in the inode) and the xattr calls take under 1 µs. The added latency is the CRC32C pass, about 12 GB/s here.
Notes
No behavior change by default:
checksum_blocksis off unless explicitly enabled, so no model evals were run. When enabled, a checksum failure turns a corrupted cache hit into a miss and recompute instead of returning the corrupted KV block.AI assistance (Claude) was used. I have reviewed every changed line and ran the tests above.
Essential Elements of an Effective PR Description Checklist
supported_models.mdandexamplesfor a new model.