mirror of
https://github.com/kvcache-ai/Mooncake.git
synced 2026-11-05 01:17:55 +00:00
[GH-ISSUE #2631] [Usage]: NoF write/read requires strict block-size alignment but neither allocators nor value_size guarantee it — is this by design? #690
Labels
No labels
ascend
auto-closed
bug
bug
CI/Build
Common
documentation
enhancement
feature request
good first issue
help wanted
high priority
MetaX
nightly-failure
pull-request
PyTorch Backend
question
RFC
Roadmap
stale
Store
Tests
Transfer Engine
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
kvcache-ai/Mooncake#690
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @mzygQAQ on GitHub (Jun 26, 2026).
Original GitHub issue: https://github.com/kvcache-ai/Mooncake/issues/2631
Describe your usage question
Description
While investigating the NoF (NVMe-oF) replica path, I found that submitSpdkNofOperation enforces strict block-size alignment on three dimensions, but none of them appear to be guaranteed by the current codebase. I'd like to understand whether this is an intentional design constraint (e.g., only uniform block-size KVCache workloads are supported) or a gap to be addressed.
The Alignment Check
In mooncake-store/src/transfer_task.cpp (lines 1280-1288), the function performs a hard alignment check before submitting any SPDK I/O:
If any check fails, the operation returns std::nullopt with no padding or retry mechanism.
Why None of the Three Checks Are Guaranteed
① buffer_address_ — NVMe offset from Master-side allocator
The NoF segment's buffer_address_ is produced by either CachelibBufferAllocator or OffsetBufferAllocator (selected via config.memory_allocator):
CachelibBufferAllocator: Slab base is 16MB-aligned (✅ for 4096), but individual allocations within a slab use CacheLib allocation class sizes (e.g., 64, 80, 96...), which are not necessarily multiples of block_size.
OffsetBufferAllocator: Uses multiplier_bits to scale offsets. For typical segment sizes (e.g., 64GB → multiplier_bits=5 → 32-byte granularity), the allocated offset is not guaranteed to be block-aligned.
② size — User's value_length, passed through without padding
The user's value_length flows directly from mc.put(key, value, value_length) → master_service.cpp (Allocate(..., value_length, ...)) → AllocatedBuffer(size=value_length) → submitSpdkNofOperation(handle, ptr, size, ...).No rounding or padding is applied at any layer. If value_length is, say, 3000 bytes with block_size=4096, the size % block_size != 0 check fails.Note: CachelibBufferAllocator::allocate does use padding_size = std::max(size, kMinSliceSize) for the actual allocation, but the AllocatedBuffer::size_ field still records the original requested size, which is what gets checked.
③ ptr — Client-side DMA buffer from ClientBufferAllocator
In real_client.cpp, when USE_NOF is defined, the client buffer allocator is created with use_spdk_dma=true:
Inside ClientBufferAllocator (client_buffer.cpp:42):
The DMA base is only 64-byte aligned, not 4096-byte aligned. The OffsetAllocator inside ClientBufferAllocator also doesn't add any block-alignment guarantee (for typical local_buffer_size < 3.75GB, multiplier_bits=0, meaning 1-byte granularity).In practice, the e2e test passes because spdk_zmalloc for large allocations typically returns hugepage-backed memory (2MB-aligned), which happens to be 4096-aligned. But this is an SPDK implementation detail, not a code-level guarantee.
Questions
Padding size up to block_size boundary in submitSpdkNofOperation (write padded zeros, truncate on read)
Enforcing block-aligned allocation in the Master-side allocators for NOF_SSD replica type
Increasing ClientBufferAllocator alignment from 64 to at least block_size (4096)
Before submitting a new issue...
@github-actions[bot] commented on GitHub (Jun 26, 2026):
Thanks for opening this issue, @mzygQAQ!
30590325A maintainer will triage this when possible. To help us respond faster, please include:
Useful links: Documentation · Contributing guide
@LujhCoconut commented on GitHub (Jun 26, 2026):
Based on my understanding, the current proposal and implementation may not yet represent a fully mature solution.
The original design was predicated on the assumption that LMCache would be used on top of Mooncake. In that design, LMCache allocates pinned CPU memory (in 4KB pages) on the computing node via
cudaHostAlloc()in CUDA. In the SPDK-based approach, enabling huge page support is additionally required to achieve zero-copy. For further details, please refer to the RFC (Issue #1940 ).As for improving the error handling (e.g., a dedicated
NOT_ALIGNEDerror code instead ofLOG(ERROR) + return nullopt), that seems like a reasonable enhancement — PRs are welcome.I will relay this concern to the designers and implementers of the RFC.
@SoftwareDogZ commented on GitHub (Jun 26, 2026):
Hi @mzygQAQ , we are the contributors of this feature. Thank you for the in-depth analysis, and we also appreciate the maintainer @LujhCoconut referencing our RFC. Below are our responses to your questions:
The original motivation of this PR is to increase KV cache capacity for LLM inference. Therefore, the current implementation is specifically designed for fixed-size KV cache chunks.
We are actively working on support for arbitrary chunk sizes. This will be addressed in an upcoming PR.
The current error reporting mechanism follows Mooncake’s native implementation. Please refer to the
BatchPutandBatchGetfunctions inclient_service.cpp: any transfer failure is reported asErrorCode::TRANSFER_FAIL. In addition, introducing new error code types would require changes across the entire call chain and multiple data structures (e.g., ErrorCode, OperationState, TransferFuture, etc.), so we would prefer to seek feedback from the community before making such changes.@mzygQAQ commented on GitHub (Jun 26, 2026):
thanks for your reply !
@github-actions[bot] commented on GitHub (Sep 25, 2026):
This issue has had no activity for 90 days and will be closed in 7 days if there is no further activity. Please comment or react if it should stay open.
@github-actions[bot] commented on GitHub (Oct 2, 2026):
Closing due to 3 months of inactivity. If this is still relevant, please comment and we can reopen.