Commit Graph

85 Commits

Author SHA1 Message Date
Dmitry Barsukoff dd9f8ae004
[Store] Allow customizing client port range (#2008)
* [ADD] MC_STORE_CLIENT_MIN_PORT and MC_STORE_CLIENT_MAX_PORT environ

* [UPD] documentation

---------

Co-authored-by: Copilot <copilot@github.com>
2026-05-05 00:13:01 +08:00
Venkat Raman 3ac7de25ac
[Store] Add lock-free MmapArena allocator for buffer mmap path (#1820)
* [Store] Add lock-free MmapArena allocator for buffer mmap path

Replace per-allocation mmap() syscalls in allocate_buffer_mmap_memory()
with a lock-free atomic bump allocator (MmapArena). Pre-allocates a
configurable pool (default 64GB) and serves allocations via CAS loop,
reducing allocation latency from ~1us (mmap syscall) to ~50ns (atomic).

Allocation lifecycle is static: all callers (ClientBufferAllocator,
global segments in RealClient::setup_internal) allocate at startup and
free at shutdown. The arena outlives all allocations, so the bump-only
(no individual free) design is correct for this usage pattern.

Feature-flagged via gflags:
  --use_mmap_arena_allocator (default: true)
  --mmap_arena_pool_size (default: 64GB)

Falls back to direct mmap() when arena is disabled, fails to init,
or is exhausted.

Cherry-picked from flow-ipc-poc branch (utils.cpp perf path only).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [Store] Fix three correctness issues in MmapArena

1. Honor caller's alignment contract: allocate() now accepts a
   per-call alignment parameter and uses max(arena default, caller
   request). allocate_buffer_mmap_memory() forwards its alignment
   argument to the arena. Previously, the caller's alignment was
   silently ignored — the arena always used 64-byte alignment
   regardless of what the caller requested.

2. Remove MAP_POPULATE from arena pool mmap: the default pool is
   64GB but callers typically use only a fraction (e.g. 4GB of
   segments). MAP_POPULATE would pre-fault all 64GB of pages upfront,
   causing seconds of startup delay and potentially triggering OOM
   on machines with less physical memory. Pages now fault on demand.

3. Make alignment_ atomic and store it BEFORE the CAS on pool_base_:
   previously alignment_ was a plain size_t written AFTER the release
   CAS, so the store was not in the happens-before relationship
   established by the acquire-release pair on pool_base_. Now both
   alignment_ and pool_size_ are stored before the CAS with the
   release fence guaranteeing their visibility to readers.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-03 14:18:18 +08:00
Stary 5ef889dd11
[TENT] Recover cooled-down RDMA rails and add failover e2e tests (#1984)
* feat(tent): improve RailMonitor recovery with exponential backoff and
configurable parameters

- Introduce exponential backoff cooldown with a configurable upper bound
(kMaxCooldown)
- Support dynamic configuration of error threshold, error window, and cooldown
via Config
- Call markRecovered on successful transfer completion to un-pause rails
promptly
- Reset error count and cooldown on recovery to prevent accumulated doubling
- Cache target_machine_id in RdmaSlice to avoid segment lookup on hot path
- Add unit tests for recovery behavior, cooldown reset, and best-device mapping

Signed-off-by: staryxchen <staryxchen@tencent.com>

* test(engine): add end-to-end failover tests and test-only transport swap hook

- Add`swapTransportForTest`method to`TransferEngineImpl`
for test-only transport injection.
- Introduce`engine_failover_e2e_test.cpp`
with scenarios: status corruption failover, budget exhaustion, mixed faults,
per-task independence, and boundary conditions for
`max_failover_attempts`.
- Register new test target`tent_engine_failover_e2e_test`in CMakeLists.

Signed-off-by: staryxchen <staryxchen@tencent.com>

* docs(tent): add failover design doc

Describe TENT's two-layer failure handling: cross-transport failover in
TransferEngineImpl and per-rail cooldown recovery in RailMonitor.
Covers fault model, state machines (with code refs), config knobs,
observability, testing, and known gaps (submit-stage failover, cooldown
reset on recovery, no CI coverage).

Signed-off-by: staryxchen <staryxchen@tencent.com>

* refactor(tent): cache RailMonitor pointer on slice to avoid hot-path string lookup

Each RdmaSlice carried the target machine_id as std::string and
asyncPollCq did a hash+strcmp lookup on worker.rails per completion.
Resolve the RailMonitor once during generatePostPath and stash the
pointer on the slice; the completion path becomes a single deref.

WorkerContext::rails now stores values via unique_ptr so a rehash
only moves the pointer slot and does not invalidate pointers already
held by in-flight slices.

disableEndpoint no longer needs a segment lookup to mark the rail
failed either -- it uses the cached pointer.

Addresses gemini-code-assist review on PR #1984.

Signed-off-by: staryxchen <staryxchen@tencent.com>

---------

Signed-off-by: staryxchen <staryxchen@tencent.com>
2026-04-30 16:49:40 +08:00
HomeDish 1b6455aa65
[TENT][Sunrise] Add sunrise_link transport, platform support, and UT … (#1915)
* [TENT][Sunrise] Add sunrise_link transport, platform support, and UT coverage

Integrate Sunrise platform/transport wiring across TENT runtime and examples, add SunriseLink end-to-end unit tests, and fix RDMA error logging pointer formatting to avoid crash during registration failure paths.

Made-with: Cursor

* [CI] Update pre-commit hook versions

Bump pre-commit hook revisions to current releases so local checks and CI use newer lint/format toolchains consistently.

Made-with: Cursor

* [TENT][Sunrise] Resolve review issues and drop stale bench target

Address review feedback in SunriseLink transport/platform paths (stream/device context, registration map synchronization, safer probe/allocator handling, and cache-refresh strategy), and remove the obsolete transfer_engine_sunrise_bench CMake target now that its source no longer exists.

* [TENT][sunrise] add engnish doc for sunrise_link

* [TENT][sunrise] restore the memory free logic in the bench, and restore config files

---------

Co-authored-by: liujialai <liujialai@sunrise-ai.com>
2026-04-28 09:47:30 +08:00
Cruz Zhao 02d1975ffd
[Store] Unified parallel tensor IO (#1389)
* [Store] add tensor object metadata and TP upsert APIs

Introduce explicit tensor object metadata for tensor read/write paths, add TP-aware tensor upsert wrappers, and update tests/docs for the new serialized layout.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 23:39:40 +08:00
Yan ae292ee837
[transfer_engine] feat: make RDMA QP pkey_index configurable via MC_PKEY_INDEX (#1985)
* [transfer_engine] feat: make RDMA QP pkey_index configurable via MC_PKEY_INDEX

Previously the QP attr.pkey_index was hardcoded to 0 during connection
setup, which prevented use of non-default partition keys. Add a
pkey_index field to GlobalConfig (default 0) that can be overridden
through the MC_PKEY_INDEX environment variable, and apply it when
transitioning the QP to INIT state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* patch

* add test and also update doc

* Use try catch blocks instead

---------

Co-authored-by: Yan Huang <yan.huang@Yan-Huangs-MacBook-Pro.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 14:01:43 +08:00
ccs668899 489c020778
[transfer_engine] fix: drain endpoint waiting list via periodic reclaim (#1952)
* [transfer_engine] fix: add periodic endpoint reclaim from monitorWorker

reclaimEndpoint() is currently invoked only from RdmaContext::endpoint()
after a new insertion. Under healthy load, insertions and evictions are
1:1 so this works. Under failure load -- many error completions trigger
deleteEndpoint(), but new-insertion traffic stalls because the dead peer
isn't generating new connection paths -- waiting_list_ grows without
bound and QPs never get destroyed.

Add a 1Hz reclaimEndpoints() call from monitorWorker on the existing
1-second context heartbeat. This decouples reclaim cadence from
insertion traffic.

See issue #1845.

* [transfer_engine] test: endpoint_store reclaim coverage for #1845

Adds unit + integration coverage for the periodic reclaim fix.

endpoint_store_test (5 tests, no RDMA device, runs under ctest):
  - reclaim drains quiescent entries on its own
  - reclaim leaves active entries alone (gate preserved)
  - reclaim is idempotent when empty
  - leak manifests without reclaim call (1118-eviction mirror of reporter)
  - reclaim works without active map (guard against insert/reclaim coupling)

endpoint_store_integration_test (requires RDMA device, not auto-registered):
  - Verifies WorkerPool::monitorWorker actually calls reclaimEndpoints at
    ~1 Hz by constructing a real RdmaContext and waiting for the tick to
    drain injected entries. Confirms the end-to-end fix wiring.

Supporting changes:
  - EndpointStore::waitingListSize() accessor (diagnostics + tests)
  - SIEVEEndpointStore::testOnlyInsertWaiting() for test injection
  - RdmaContext::endpointStore() accessor (diagnostics + tests)

* [docs] note periodic reclaim behavior and #1845 symptom

- design/transfer-engine: add a sentence to Endpoint Management explaining
  that waiting_list_ drains both on insertion and on the monitorWorker
  heartbeat, so accumulated reclaim does not stall under failure load.
- troubleshooting: extend the "Failed to create QP: Cannot allocate
  memory" entry with a bullet pointing at issue #1845 so operators
  seeing the symptom find the cause and the fix.

* [transfer_engine] fix: guard FIFOEndpointStore::waitingListSize with atomic counter

Per PR #1952 review: FIFO variant returned waiting_list_.size() on
std::unordered_set without holding endpoint_map_lock_, racing
concurrent modification. Mirror the SIEVE pattern with an atomic
waiting_list_len_ incremented in delete/evict, decremented in reclaim.

* [transfer_engine] test: suppress intentional RdmaTransport leak under LSAN

CI build (3.10/3.12) runs with -DENABLE_ASAN=ON and LSAN flagged the
5 × 288 byte allocation the test fixture intentionally leaks
(~RdmaTransport dereferences a null metadata_ unless install() ran).
Gate on __SANITIZE_ADDRESS__ / __has_feature and mark the pointer with
__lsan_ignore_object so real leaks are still caught.

* [transfer_engine] fix: widen waiting_list_len_ atomic to size_t

waitingListSize() returns size_t but the underlying counter was atomic<int>,
which quietly narrowed on load. Promote to atomic<size_t> in both FIFO and
SIEVE so the getter is a clean pass-through with no implicit conversion.

* [transfer_engine] docs: pin reclaimEndpoint lock contract on base interface

monitorWorker now calls reclaimEndpoint() via RdmaContext; it already
acquired endpoint_map_lock_ internally, but nothing declared that. Codify
the precondition on the base so future callers know not to hold the lock.
RWSpinlock is non-reentrant, so recursive acquisition would deadlock.

* [transfer_engine] refactor: narrow RdmaContext endpoint store test surface

Previously exposed a raw EndpointStore* via RdmaContext::endpointStore()
for the integration test. A raw pointer is easy to misuse outside of
tests and couples the caller to the concrete store via dynamic_cast.

Replace with two narrow methods on RdmaContext: waitingListSize() (value
return) and testOnlyInsertWaiting(shared_ptr<RdmaEndPoint>). The latter
is lifted onto the EndpointStore base interface and implemented on both
FIFO and SIEVE, so the integration test no longer downcasts.

* [transfer_engine] test: register endpoint_store_integration_test with ctest

Integration test was previously unregistered and invoked manually. Now
self-skips via GTEST_SKIP when no RDMA device is present, so it runs
cleanly on CI runners without RDMA (skips) and on rxe/mlx5 hosts
(executes). Labeled "rdma" for ctest -L filtering.

* [transfer_engine] perf: short-circuit FIFO reclaim when waiting list is empty

monitorWorker now drives reclaim at ~1 Hz regardless of activity. On FIFO
this grabbed endpoint_map_lock_ as WriteGuard every tick even in the
common steady-state case where waiting_list_ is empty. Add the same
counter-check short-circuit SIEVE already has.

* [transfer_engine] test: skip integration test when RdmaContext::construct fails

GHA ubuntu-22.04 runners enumerate a phantom mlx5_0 via ibv_get_device_list
without a working port/GID, so pickRdmaDevice() returns a non-empty name
and the earlier GTEST_SKIP on empty device list doesn't fire. Then
construct() fails with ERR_CONTEXT and the hard ASSERT_EQ fails the test.

Convert the assertion to a GTEST_SKIP on construct failure. Matches the
"attempt setup, skip on failure" convention used elsewhere in the repo
(e.g., client_local_hot_cache_test.cpp:794-799).
2026-04-27 10:32:34 +08:00
yejj 889326a848
[Doc] update conductor design & api docs (#1977) 2026-04-27 01:10:13 +08:00
王鹤男 634b709731
[TE] EFA SRD shared-endpoint refactor: drop per-peer fid_ep model (#1944)
* feat(efa): idempotent warmupSegment for repeated calls

Adds EfaContext::peekEndpoint() — a non-creating, normalized-key lookup
— and uses it in EfaTransport::warmupSegment() to short-circuit when
every (local_ctx, peer_nic) pair is already connected. Repeated warmup
calls on the same segment now return immediately instead of firing a
256-thread std::async fan-out each time.

Verified on p6-B300 (16 NICs × 16 peer NICs = 256 endpoints):
  iter 0: 7.95s  (full handshake)
  iter 1: 0.000s (short-circuit hit)
  iter 2: 0.000s (short-circuit hit)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(efa): evict-on-ENOMEM + drop-on-failure for endpoint store

Recover from QP exhaustion (fi_enable returns -FI_ENOMEM at the device
cap, 768/device on p6-B300) and prevent dead endpoints from piling up
under callers that drift endpoint keys (e.g. keys carrying a timestamp).

Three places:

* EfaContext::endpoint (slow path): on construct failure, evict stale
  endpoints once and retry. Eviction only scans when we actually ran
  out of room, so normal traffic pays nothing.

* EfaTransport::warmupSegment: if setupConnectionsByActive fails, drop
  the endpoint via deleteEndpoint(normalizedKey) instead of leaving a
  dead fid_ep holding its QP slot.

* EfaContext::submitPostSend: if submitPostSend returns non-zero and
  the endpoint is no longer connected, drop it for the same reason.

Reproduced on B300: without the fix, injecting ":drift<iter>" into the
peer_nic_path exhausts fi_enable at iter 48 (768/16 peer NICs). With
the fix, 325 iterations complete with RSS bounded at ~6 GB.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(efa): SRD shared-endpoint refactor — drop per-peer fid_ep model

Under SRD (FI_EP_RDM), a single fid_ep per local NIC can address any number
of peers via fi_av_insert.  The old model created 16 per-peer endpoints per
connection (one per local NIC), consuming 16 QPs each — hitting the 768 QP
cap after only 48 peers and forcing an LRU + evict-on-ENOMEM dance.

This change:
- EfaContext owns a single shared fid_ep + peer address vector (`peer_map_`)
- EfaEndPoint becomes a thin per-peer fi_addr_t holder (no fi_endpoint,
  no fi_enable) — handshake is RPC + fi_av_insert only
- submitPostSend delegates to EfaContext::submitSlicesOnPeer, using the
  peer's AV index against the shared endpoint
- setPeerNicPath detaches stale AV slot on peer reconnect so drift scenarios
  re-handshake cleanly
- Deletes EfaEndpointStore + LRU/ENOMEM eviction machinery — no longer needed
- warmupSegment short-circuit updated for the shared-endpoint flow

P5EN drift stress (1 target ↔ 1 initiator, customer shape 328 GB, 16 NIC,
180s target lifetime):
  - iter 0 (fresh peer) first_batch: 33.6 ms   (was ~8.95 s → 266× faster)
  - iter 1–3 (drift)   first_batch: 260–340 ms (was ~8.95 s →  ~26× faster)
  - steady: ~215–220 GB/s, 0 failures across 204 M completed ops
  - QP growth per added peer: 0 (was 16) — no more 48-peer cliff

See mooncake-transfer-engine/example/efa_srd_refactor_validation/ for raw
CSV and target-teardown timings.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(efa): expose warmup_efa_segment in Python binding

The C API (warmupEfaSegment) and Rust FFI (warmup_efa_segment) already
pre-connect every (local_ctx, peer_nic) pair so the first submitTransfer
does not stall on handshake RPC + fi_av_insert.  The pybind TransferEngine
did not expose this, so Python-driven integrations (vLLM / SGLang) could
not benefit from the first-call latency improvement from the SRD shared-
endpoint refactor (iter 0 first_batch 33.6 ms vs 8.95 s baseline).

Mirror the C API shape: thin pass-through that dynamic_casts the installed
"efa" transport and calls EfaTransport::warmupSegment.  No-op on non-EFA
builds or when the EFA transport is not installed.

Tested: built with USE_EFA=ON on p5en, imported engine.TransferEngine, and
confirmed `warmup_efa_segment(segment_name: str) -> int` is bound.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(efa): apply code_format.sh (clang-format-20)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(efa): drop internal drift_stress/validation dirs + stale gflags doc note

- Remove mooncake-transfer-engine/example/drift_stress/ — depends on
  the out-of-tree customer_pattern Rust binary and isn't usable by
  upstream contributors.
- Remove mooncake-transfer-engine/example/efa_srd_refactor_validation/
  — validation artifacts for the SRD refactor; the headline numbers
  live in the PR description instead.
- Remove the libgflags-dev note from docs/.../efa_transport.md — it
  is pulled in transitively by dependencies.sh and no longer needs a
  manual install step.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(efa): close shared endpoint before dropping peer map in teardown

Calling fi_av_remove() on peer addresses after the shared fid_ep was
still open — or calling it at all during context teardown when the AV
itself is about to be fi_av_close()d — trips a libfabric EFA-provider
assertion, causing the efa_transport_test unit tests to segfault on
engine destruction.

Reorder EfaContext::deconstruct() to close shared_ep_ first, then
detach every peer handle via a new markDetachedForTeardown() that just
resets the AV-slot field without calling fi_av_remove(). fi_av_close()
below invalidates every slot in one shot, so no per-slot removal is
required on the teardown path.

Verified: all 5 EFATransportTest cases (InstallTransport, LoopbackWrite,
WriteAndRead, MultiWrite, StressMultipleBatches) now pass on P5EN.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* test(efa): add coverage for warmupSegment, batch register, large xfer, re-open

Five additional EFATransportTest cases, filling gaps in the existing
suite (which only exercised install + 4 single-buffer write/read paths):

  - WarmupSegmentLoopback  — covers EfaTransport::warmupSegment() and
    its idempotent short-circuit on the second call, plus the empty /
    self-name no-op path.
  - WarmupSegmentNotFound  — warmupSegment must fail cleanly (not hang)
    for an unknown segment name.
  - RegisterMemoryBatch    — registerLocalMemoryBatch +
    unregisterLocalMemoryBatch round-trip.
  - LargeTransfer          — 128 MB buffer, 64 x 1 MB slices; exercises
    WR / CQ pacing in EfaContext::submitSlicesOnPeer well past the
    16 x 64 KB MultiWrite ceiling.
  - RepeatedOpenSegment    — openSegment() on the same peer repeatedly
    must keep transferring correctly; guards the setPeerNicPath detach
    path that target-restart drift depends on.

docs/.../efa_transport.md's Unit Tests table updated to match.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): restrict CTest invocation to the efa tests

Running the full ctest suite on an EFA-only host trips etcd /
mooncake_master requirements in the TCP / metadata / store tests, which
can read as "EFA broke the build". The EFA doc should not recommend
that invocation — filter to the two EFA binaries and call out the
reason in a note.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): drop redundant MC_METADATA_SERVER / MC_LOCAL_SERVER_NAME block

The defaults (P2PHANDSHAKE and 127.0.0.1:12345) are what the loopback
unit tests actually want, and nothing in the current test suite needs
an override, so documenting these "env var exports" next to the test
invocation just makes readers wonder whether they are mandatory.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): drop obsolete CUDA_VISIBLE_DEVICES tip for CPU-to-CPU runs

The tip existed because libfabric's EFA provider used to dlopen
libcudart at fi_getinfo time, creating a CUDA context even for
CPU-only benchmarks. EfaContext::construct now sets FI_HMEM=system
when the build is not GPU-enabled, which already prevents that
context from being created — the CUDA_VISIBLE_DEVICES="" workaround
is no longer needed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): lead with a bench command that hits line rate

The previous "Initiator Node" snippet used block_size=65536 /
threads=8 / buf=1GB, which reaches only ~50 GB/s on an 8x400G host
and reads as "EFA is broken" to anyone copy-pasting it. Replace with
block=1MB / threads=32 / buf=4GB — the same values that produce the
GB/s numbers quoted in the Benchmark Results tables — and add a short
sentence telling readers exactly why block_size matters. Also clarify
that the MC_SLICE_SIZE no-effect note covers both CPU-to-CPU and
GPU-to-GPU paths (verified: no EFA code reads globalConfig().slice_size,
only rdma_transport and kunpeng_transport do).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): drop MC_SLICE_SIZE references, sync target --buffer_size

EFA transport never reads globalConfig().slice_size — the only readers
are rdma_transport and kunpeng_transport — so the env-var table row,
the "MC_SLICE_SIZE has no effect" tuning-tip bullet, and the
pre-optimization tuning-history details block were all documentation
debt rather than user guidance. Drop all three.

Also: the target command defaulted to --buffer_size=1GB (the flag's
default), but the recommended initiator command now uses 4GB. Since
the target allocates and registers exactly FLAGS_buffer_size bytes and
the initiator writes into offsets [0, buffer_size), they have to
match. Add --buffer_size=4294967296 to the target snippet and a short
line calling out the constraint.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(efa): skip preTouchMemory for GPU buffers, clarify target flags

preTouchMemory() does a CPU-side store per page, which was gated only
by "chunk >= 4 GiB". That trips a segfault the moment a user registers
a >=4 GiB cudaMalloc buffer — exactly what the recommended benchmark
config does. Restrict the pre-touch to host (cpu:*) memory so VRAM
registration stays a pure libfabric call.

Also amend the benchmark docs:
  - call out that --use_vram / --gpu_id apply to the target too, and
    that GPU-to-GPU runs need --gpu_id=-1 on both sides
  - mention --use_vram=false as the alternative to a -DUSE_CUDA=OFF
    build for CPU-to-CPU runs

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): default benchmark snippet to gpu_id=-1 + threads=16

Align the benchmark quick-start with what actually reaches line rate
on a p5en.48xlarge pair (≈350 GB/s write, verified). The previous
snippet recommended --threads=32 and no --gpu_id override, which:

  - ran on one GPU (default gpu_id=0), so buffers sat on one NUMA
    node and half the NICs were cross-NUMA — settled at ≈56 GB/s
  - ran into the SRD shared-endpoint WR cap (16 × 256 = 4096 WRs
    vs 32 × 128 = 4096 outstanding slices, zero headroom) and
    triggered "timed out waiting for CQ drain"

Rework the section: lead with the two knobs that matter (--gpu_id=-1
on both sides, --block_size=1048576), add --gpu_id=-1 to the target
snippet for symmetry, switch the initiator to --threads=16, and
explain in a note why 16 is the ceiling (so readers know where the
limit comes from, not just that we picked it).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): complete the Key Parameters table

The table was missing several flags that the bench snippet in the
same section actually uses (--mode, --protocol, --metadata_server,
--segment_id, --use_vram), and some of the flags it did list had
defaults / descriptions that did not match the binary (e.g. default
operation is read, not write). Sync every row to DEFINE_* in
transfer_engine_bench.cpp and add explicit "what this is for on EFA"
hints next to the two flags (--block_size, --gpu_id) that most
determine whether the run hits line rate.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): reorder benchmark sections by peak throughput

Lead with p6-b300 (752 GB/s peak), then p5en (347 GB/s), then
p6-b200 (313 GB/s). Readers skim the first table to decide whether
EFA transport is fast enough for them; putting the best-performing
platform first avoids undersell.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): reorder benchmarks by hardware generation, not raw GB/s

Previous reorder put p5en (H200) above p6-b200 (B200) because the
p5en rows happen to show a higher headline number, but B200 is a
newer generation than H200 and the p6-b200 numbers there are an
older snapshot. Fix the ordering to reflect hardware recency:
p6-b300 → p6-b200 → p5en. Same change applied to the
Cross-Transport Comparison table.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): refresh p5en bench results (366 GB/s write / 304 GB/s read)

Re-swept on P5EN (H200, 16×200G) with the SRD shared-endpoint build
and --buffer_size=4GB per GPU. New peaks:

  - Write: 365.66 GB/s @ threads=16, batch=128 (up from 347 GB/s)
  - Read:  303.78 GB/s @ threads=16, batch=32  (up from 308 GB/s,
           but now with a clear optimal config)

The new table preserves enough rows to show the two interesting
axes — write wants big batches, read wants small ones — and the
Cross-Transport Comparison is updated to 366 GB/s (~91% of the
400 GB/s line rate). B200/B300 rows are unchanged (no hardware
available to re-sweep).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): mark B200/B300 bench rows stale, refresh p5en CPU, drop cross-transport table

- p5en CPU-to-CPU re-swept on current SRD shared-endpoint build:
  peak write 213.57 GB/s @ threads=48/batch=32, peak read 212.18 GB/s
  @ threads=16/batch=32 (vs old 192 GB/s / 182 GB/s). Table shows a
  few representative points — throughput is essentially flat across
  the parameter grid because the run is DRAM-bound.
- B200 and B300 sections tagged as predating the SRD refactor and the
  recent tuning work; a re-sweep is pending hardware availability.
- Drop the "Cross-Transport Comparison" subsection and the
  "EFA vs RoCE RDMA" paragraph — both were derived numbers that
  quickly rot and were already redundant with the per-platform
  tables above them.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): add block_size + buffer_size sweep tables as evidence

Two sweeps on p5en GPU-to-GPU (SRD shared-endpoint build, --gpu_id=-1)
at the peak config (threads=16, batch=128), backing up the tuning
claims elsewhere in this file:

  - block_size: 64 KB default reaches only 26% of peak. Write
    throughput climbs steeply through 512 KB, plateaus between 1 MB
    and 2 MB. 2 MB is MC_EFA_STRIPING_THRESHOLD (a different code
    path). 1 MB is the recommended value — within 4% of the 2 MB
    peak and safely below the striping boundary.
  - buffer_size: only needs to clear block × batch × threads (2 GB
    in the peak config). 2 GB vs 4 GB differs by ~3% on write, read
    is flat within noise. The example commands use 4 GB purely as
    a generous default, not because smaller fails.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): rewrite Tuning Tips around the SRD shared-endpoint model

Two stale claims under Tuning Tips were written for the old per-peer
endpoint code:

  - "Increase threads to 32-48": under the shared endpoint each NIC
    has a 256 WR cap, and threads × batch past 16×256 = 4096 trips
    the CQ-drain timeout. The sweep on p5en shows 16 threads is the
    ceiling, not the floor.
  - "Write peaks at threads=32, read at threads=16 / buffer=2GB max
    per GPU": both taken from the pre-refactor B300 snapshot.
    Current p5en peaks are both at threads=16; the 2GB/GPU limit
    was the VRAM preTouch segfault that is now fixed.

Rewrite the bullets to describe what the SRD shared-endpoint
actually constrains: block_size sweet spot, threads × batch WR
cap, the write-vs-read batch-size split, and --gpu_id=-1 on both
sides. Add an explicit line that buffer_size only needs to clear
block × batch × threads (pointing readers at the sweep table).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(efa): remove broken per-request striping across NICs

submitTransferTask had a branch that, when request.length exceeded
MC_EFA_STRIPING_THRESHOLD (default 2 MB), split the request into
num_nics slices and dispatched one per NIC. The intent was to speed
up large single transfers by paralleling across all NICs.

A sweep on p5en (SRD shared-endpoint build, 16 NICs x 200G) shows
the branch is a ~20x negative optimization in every bench config:

  block=1 MB, threads=16, batch=128: ON 16 GB/s vs OFF 366 GB/s
  block=8 MB, threads=16, batch=16:  ON 18 GB/s vs OFF 355 GB/s
  block=32 MB, threads=16, batch=4:  ON 18 GB/s vs OFF 328 GB/s

Even the designed-for scenario (threads=1, batch=1, single huge
request) only wins by 1.2x (27 vs 23 GB/s) — far below the 16x
expected from parallel dispatch, because the per-slice post_lock /
peer lookup still serialize the dispatch. And that "win" is only
reachable with threads=1 — any realistic caller with multiple
threads can parallelize on its own without this mechanism.

Since the branch silently degrades every common bench / workload
configuration above the 2 MB threshold and delivers no real win
even in its best case, delete it:

  - efa_transport.cpp: drop the LARGE TRANSFER if-branch and the
    kStripingThreshold read.
  - config.h / config.cpp: drop the efa_striping_threshold field
    and the MC_EFA_STRIPING_THRESHOLD env var.
  - docs/.../efa_transport.md: drop the Environment Variable row,
    the "Note on EFA slicing" striping explanation, and the
    "striping off" callouts in the benchmark tables and tuning
    tips.

Verified: all 10 EFATransportTest cases pass, and the peak p5en
bench run is unchanged (352.81 GB/s write @ threads=16, batch=128).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): number the sequential subsections for easier skimming

Four groups of level-3 / level-4 headings in this doc read as
step-by-step instructions (do A first, then B), but only two of
them were numbered while the others relied on order alone. Result:
readers had to count positions to tell "how far through" they were.

Number every such group consistently:

  - Performance Benchmark: Target Node (1) / Initiator Node (2)
  - Usage with vLLM: Prefill Instance (1) / Decode Instance (2)
  - Benchmark Results: p6-b300 (1) / p6-b200 (2) / p5en (3)

Reference-style sections (Key Parameters, Tuning Tips, Warmup,
Technical Details, Troubleshooting) stay unnumbered — those aren't
ordered and numbering them would imply a reading path that
doesn't exist.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* test(efa): add efa_first_submit_probe for warmup / first-submit timing

A standalone cross-node probe that measures, separately:
  - warmupSegment() latency, and
  - per-submit latency for the first N single-transfer submits

so we can isolate the handshake / av_insert cost (warmup=OFF makes
it land on submit #0) and compare pre-refactor vs post-refactor
code without having to squint at 10s throughput averages.

Not enabled by default ctest — only built when USE_EFA=ON. Meant
for manual two-host runs alongside transfer_engine_bench.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): replace warmup numbers with a cross-branch p5en measurement

The old "Eager endpoint warmup" numbers (4 s stall / 13.5 ms warmed)
were from a B300 snapshot that predated the SRD shared-endpoint
refactor, so they described the OLD code. Replace with a fresh
cross-node measurement on p5en that compares both branches head to
head using efa_first_submit_probe:

  - Warmup itself: 1.1 s (SRD shared endpoint) vs 17 s (per-peer
    fid_ep on upstream main) — ~15x faster and much more stable
    (SRD runs were all 1.13-1.14 s; old code swung 9-17 s across
    three reps).
  - Cold first submit with NO warmup: 26 ms (SRD) vs 99 ms (old) —
    ~4x faster, because the shared endpoint removes the per-peer
    fi_endpoint / fi_enable step that used to dominate the first
    send.

The prior text's "first-batch stall" framing also reads as if the
whole first submitTransfer always pays the full handshake cost.
That's not quite how it works — the initiator round-robins across
local NICs, so only a handful of pairs warm on each call, and the
stall amortizes across the first several submits. Fix the wording.

Add a pointer to the probe source (example/efa_first_submit_probe.cpp)
so the measurement is reproducible.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): reframe "first-request latency" around two audiences

The previous version led with a long explanation of warmupSegment and
its internals, which made it sound like callers had to opt in to get
any first-request speedup from this PR. That isn't the case: the SRD
shared-endpoint refactor cuts the cold submit from 99 ms to 26 ms
automatically, and vLLM / SGLang (which don't call warmupSegment) see
that 4x win without any integration work on their side. The explicit
warmupSegment API is an additional 15x improvement on top of that,
but it matters mainly to direct Mooncake callers.

Restructure the section accordingly:

  - Lead with a 2x2 table showing both numbers side by side.
  - Frame the ~4x cold-submit win as the default, no-code-change
    benefit everyone gets.
  - Frame warmupSegment as the opt-in path for callers that want
    sub-10 ms first-request latency.
  - Explicitly note that vLLM / SGLang currently don't call it.
  - Keep the peer handshake-daemon bottleneck note so readers
    understand why the warmup scales linearly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): reference #1944 explicitly instead of "this PR"

"This PR" dangles once the doc lands on main — it's fine in review
context, less fine afterwards. Use the concrete issue number so
readers (including future us) can follow the link.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): unwrap soft-wrapped paragraphs, let the renderer flow them

Several blockquote notes, tuning-tip bullets, and the "first-request
latency" section used ~70-column soft wraps, which look fine rendered
but make the raw markdown look ragged — the line after 'Peer
addressing resolves lazily:' used to stop before the line was
actually full, which reads as a formatting bug in plain text. Let
each logical paragraph / bullet be a single line and defer wrapping
to the browser / sphinx renderer. No rendered change.

Also update the PR body on #1944 the same way.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): fix post-refactor stale references (architecture, thread safety, comparison)

Four places still described the pre-#1944 code:

  1. docs/.../efa_transport.md "EFA Transport Architecture" diagram —
     showed fid_ep inside EfaEndpoint, which is wrong under the
     shared-endpoint model. fid_ep lives on EfaContext (shared_ep_);
     EfaEndPoint only holds the peer's fi_addr_t AV slot. Redraw.

  2. docs/.../efa_transport.md "Thread Safety" — said the transport
     "adds per-endpoint spinlocks" (plural, per-endpoint). In the
     new code there's exactly one post_lock_ per EfaContext guarding
     the shared fid_ep. Reword.

  3. docs/.../efa_transport.md "EFA vs RoCE RDMA" comparison rows —
     used the pre-refresh p5en GPU number (347 GB/s) and the stale
     B200 row (313 GB/s). Replace with the current p5en peak from
     the benchmark tables above (365 GB/s GPU, 213 GB/s CPU), drop
     the row pointing at a now-absent B200 re-sweep.

  4. efa_context.cpp:589 — "Fast path: peer info pre-resolved by
     submitTransferTask's striping path". The striping path was
     removed in an earlier commit in this PR; the fast path now
     just catches slices whose peer_nic_path the caller already
     filled in. Reword without referencing the removed mechanism.

No behavioral change.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(efa): address pr review — drop unused params, sysconf once, drop friend-class, expand probe comment

Addresses trivial review feedback on #1944:

  - EfaContext::construct() no longer takes num_comp_channels / port /
    gid_index. These three parameters were plumbed through from the
    original RDMA-era signature but the EFA/libfabric path never read
    them; the previous commit just silenced warnings with (void) casts.
    Remove them from the signature and the one caller in
    EfaTransport::installSglangTransport.
  - preTouchMemory() was calling sysconf(_SC_PAGESIZE) twice (once
    for the >0 check and once for the value). Cache the result in a
    local.
  - `friend class EfaEndPoint` in efa_context.h was unnecessary —
    EfaEndPoint only touches public methods on EfaContext
    (nicPath, localEpAddr, engine, insertPeerAddr, removePeerAddr,
    submitSlicesOnPeer). Drop the friend decl.
  - Expand the header comment on efa_first_submit_probe.cpp to say
    what problem it exists to measure and why transfer_engine_bench
    alone isn't sufficient — reviewer asked what the example is for.

No behavioral change.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* perf(efa): faster hex<->binary AV address handling

Reviewer pointed out two sources of overhead in the handshake path:

  1. localEpAddr() built the hex string via std::ostringstream with
     std::hex / std::setw / std::setfill, which pulls in stream
     formatting for every byte. Replace with a direct table-driven
     encoder writing into a pre-sized std::string.
  2. insertPeerAddr() decoded the hex using substr() + strtol() for
     every byte (a temporary std::string and a libc base-16 parse per
     pair). Replace with a single pass using a hexNibble() helper and
     a pre-sized buffer.
  3. Loopback called insertPeerAddr(localEpAddr()), encoding the
     bytes to hex and then immediately decoding back. Expose the raw
     bytes via localEpAddrBytes() and add an insertPeerAddrBytes()
     overload; loopback now skips the round-trip entirely.

Handshake path is not the dominant cost in steady-state serving, but
warmupSegment() fires 256 of these on a fresh 16x16 topology and
every one of them was doing the extra work. The new path also avoids
the per-byte std::string allocation (strtol path).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor(efa): use std::atomic for wr_depth / cq outstanding, fix O(N^2) erase

Replace `volatile int` + __sync_* builtins with std::atomic<int> on the
shared-endpoint pacing counters (EfaContext::wr_depth_ and
EfaCq::outstanding).  `volatile` never implied atomicity under the C++
memory model, and mixing it with __sync builtins was technically UB; the
atomic version is both portable and more explicit about the intended
memory ordering (acq_rel on the mutating ops, relaxed on the speculative
load used for CAS).

Also fix an O(N^2) batch consumption pattern in submitSlicesOnPeer:
`slice_list.erase(begin, begin + batch_count)` shifted the tail on every
iteration.  Consume via a moving cursor instead, and splice retry slices
in place when -FI_EAGAIN forces a partial post.

Behavior is unchanged on the happy path; the retry path now preserves
the original slice order at the cursor, matching the previous insert-at-
front semantics.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(efa): drop stale efa_latency_bench.{py,png}, document efa_first_submit_probe

The `efa_latency_bench.py` script and its `efa_latency_bench.png` output
shipped with the original EFA transport PR (#1509) two years ago. No
markdown doc references them, the script hard-codes old private IPs as
defaults, and nothing guarantees the chart is still representative.
Remove both.

Expand the First-request latency section of efa_transport.md to actually
document `efa_first_submit_probe`: what it measures (cold-submit +
eager-warmup cost, which `transfer_engine_bench`'s 10s average hides),
how to run it (target / initiator commands), the expected output layout,
all flags, and the two situations where it is worth running (deciding
whether your app needs `warmupSegment()`, and comparing PR branches on
the same hardware). Marked it explicitly as EFA-specific — RDMA/TCP
transports do not have an equivalent warmup concept, so folding this into
`transfer_engine_bench` would muddy the generic benchmark for no gain.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: EC2 Default User <ec2-user@ip-172-31-8-212.us-west-1.compute.internal>
2026-04-23 16:52:27 +08:00
Copilot 255e287bc1
Refactor ASIO shared target into mooncake-common (#1926)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: stmatengss <11641725+stmatengss@users.noreply.github.com>
Co-authored-by: zhang zuoyuan <zhangzuo21@mails.tsinghua.edu.cn>
2026-04-22 00:15:33 +08:00
lujh 0f22234d0b
[Store] unify file storage backend env vars under MOONCAKE_OFFLOAD_ p… (#1929) 2026-04-21 11:36:54 +08:00
王鹤男 952da65651
[TE] PTE-aware auto-split large MR registration for EFA transport (#1912)
* feat(efa): auto-split large MR registrations exceeding max_mr_size

Buffers larger than the EFA device's max_mr_size are now transparently
split into chunks, each registered as a separate MR. This fixes the
silent truncation bug where only the first max_mr_size bytes were
registered, causing transfers to unregistered regions to fail at runtime.

Key changes:
- Query EFA device max_mr_size via ibverbs during init (libfabric does
  not expose this) and clamp globalConfig accordingly
- Auto-split buffers > (max_mr_size - 1GB) into chunks in
  registerLocalMemoryInternal, each with its own BufferDesc metadata
- Track chunk mappings for proper cleanup in unregisterLocalMemory
- Change lkey()/rkey() from exact-match to range lookup (matching
  mrDesc() pattern) so key lookups work for any address within a chunk
- Replace silent truncation in EfaContext with a hard error as safety net
- Remove preTouchMemory truncation to touch the full buffer

Tested on P5EN (16 EFA NIC, max_mr_size=192GB): 191GB single-chunk
registration succeeds. Auto-split triggers correctly for larger buffers
(200GB splits into 191GB + 9GB). Total registerable size per buffer is
bounded by system pinned_vm limits (~191GB on 16-NIC P5EN).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(efa): per-NIC partition for large buffer MR registration

Each EFA NIC can only register up to max_mr_size total. The previous
auto-split approach registered every chunk on ALL NICs, hitting the
per-NIC limit for buffers > max_mr_size. This change assigns each
chunk to a disjoint subset of NICs, enabling registration of buffers
up to max_mr_size × num_NICs (e.g. ~1.5TB on P5EN with 16 NICs).

Key changes:
- chunk_limit = max_mr_size / 2 (was max_mr_size - 1GB) for headroom
- NIC assignment: chunks distributed evenly across available NICs
- selectDevice(): skips NICs with rkey=0 (unassigned for that chunk)
- Striping path: filters by lkey!=0 to avoid unregistered NICs
- Unregister: only deregisters from assigned NICs per chunk
- ChunkRegistration struct tracks per-chunk NIC assignments

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(efa): PTE-aware auto-split replaces conservative max_mr_size/2 threshold

The previous chunk_limit of max_mr_size/2 (~96GB on P5EN) caused unnecessary
buffer splitting even when hugepages were available. This detects the actual
backing page size via /proc/self/smaps and computes the PTE-based limit:
  - 4KB pages: 22M PTEs × 4KB = 88GB (genuine hardware constraint)
  - 2MB hugepages: 22M PTEs × 2MB = 44TB (effectively max_mr_size)

Verified on P5EN (H200, 16 EFA): 100GB pool with hugepages no longer splits,
restoring full 16-NIC throughput (108 GB/s vs 46 GB/s with the old threshold).
MR registration time dropped from 302s to 1.6s.

Adds MC_EFA_MAX_PTE_ENTRIES env var for override (default 22M).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(efa): add KV cache prefix transfer benchmark script

Python benchmark to measure EFA transfer performance for LLM prefix
cache hit scenarios. Tests different pool sizes (10GB-500GB) and prefix
lengths (4K-32K tokens) to evaluate per-NIC partition impact on
transfer latency and throughput.

Default KV bytes/token matches GLM-5.1 (754B MoE, MLA attention):
(kv_lora_rank=512 + qk_rope_head_dim=64) * 2 * 78 layers = 88KB/token

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(bench): add connection warmup before benchmark loop

The first prefix size's measurements were skewed by EFA connection
establishment (openSegment, endpoint creation). Add 3 small transfers
before entering the benchmark loop to warm up the connection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(bench): per-offset warmup and p50 throughput reporting

Warmup now exercises all offsets the benchmark will measure, eliminating
first-access TLB/page-fault outliers (4K token p99 dropped from 80ms to
3.5ms). Throughput is reported from p50 latency instead of avg for more
stable numbers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(bench): add --threads option for concurrent prefix transfer

Adds optional multi-threaded transfer support. Each thread transfers a
chunk of the prefix in parallel via separate transfer_sync_read calls.
Default is 1 (single transfer, same as before). Testing shows threads=2
matches single-thread throughput (~108 GB/s), while higher values add
scheduling overhead with no benefit since EFA already stripes internally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(efa): full NIC coverage for multi-chunk MR registration

When a buffer exceeds max_mr_size and must be split into multiple chunks,
register every chunk on ALL NICs instead of disjoint per-NIC partition,
as long as total PTE usage per NIC fits within the PTE budget.

With hugepages (2MB), 500GB buffer uses only 250K PTE/NIC (budget: 24M),
so all 16 NICs cover every address. Falls back to disjoint partition when
PTE budget is exceeded (e.g. 4KB pages with large buffers).

500GB pool throughput: 35 GB/s (disjoint, 5-6 NIC) → 108 GB/s (full, 16 NIC).
Registration time unchanged (~9.5s) due to parallel MR registration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(bench): add batch memory registration benchmark

Test script for registering multiple independent memory blocks
(e.g. multi-tenant KV cache pools). Supports both per-block
register_memory and batch_register_memory APIs. Target mode
allocates and registers N blocks; initiator mode transfers
data and measures throughput.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: apply clang-format to EFA transport files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(efa): expose discoverTopology C API and Rust bindings

Add discoverTopology() to the C API and discover_topology()/install_transport()
to the Rust bindings, enabling EFA transport initialization from C/Rust callers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test(efa): add C API test for discoverTopology and EFA transport

Verify that the new discoverTopology() C API correctly populates the
device list, enabling installTransport("efa") and memory registration
via the pure C interface (used by Rust/Go bindings).

All 4 tests passed on p5en.48xlarge (16 EFA NICs).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(efa): O(log n) MR lookup and chunk registration rollback

- Replace unordered_map with std::map for mr_map_ and use upper_bound
  for O(log n) range lookups in rkey/lkey/mrDesc instead of O(n) scan
- Add rollbackChunks lambda to unregister already-registered chunks on
  failure in registerLocalMemoryInternal, preventing MR leaks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: apply clang-format to efa_c_api_test.cpp

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: rename thr_tag to thread_tag to pass typos spell check

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(efa): round-robin multi-chunk MR and large MR registration test

When a buffer splits into more chunks than available NICs, round-robin
assign chunks across NICs with per-NIC PTE budget validation, instead
of hard-failing with "Buffer requires N chunks but only M NICs".

Add efa_single_nic_large_mr_test: tests single-NIC and all-NIC large
MR registration with hugepages. Supports --chunk_gb for multi-buffer
mode (e.g. 200×2GB).

Verified on P5EN (16 EFA NIC, 2MB hugepages):
  - 1 NIC × 200×2GB (400GB): 53.7s
  - 16 NICs × 200×2GB (400GB): 64.8s
  - 1 NIC × 200GB single buffer: 2.7s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(efa): add cross-node transfer test for multi-buffer MR registration

Tests 200x2GB buffer registration on all NICs with actual data transfer
between two P5EN nodes. Supports target/initiator modes with single-read
and multi-block batch benchmarks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(efa): avoid CUDA context leak when built without GPU support

libfabric 2.4's EFA provider dlopens libcudart/libcuda during
fi_getinfo/fi_domain to detect HMEM support, even though the caller
never touches GPU memory. This creates a CUDA primary context on
GPU 0 and permanently holds ~616 MiB of device memory.

When Mooncake is built with USE_CUDA=OFF (and USE_HIP=OFF), set
FI_HMEM=system before fi_getinfo and drop FI_MR_HMEM from the domain
hints so the provider skips GPU hmem initialization entirely.

* feat(efa): multi-thread initiator and wildcard location for 16-NIC coverage

Register target buffers with wildcard location "*" instead of "cpu:0"
so initiator-side remote NIC selection distributes evenly across all 16
NICs (both NUMA nodes). With "cpu:0", selectDevice only picked NUMA-0's
8 NICs, leaving NUMA-1 idle — throughput capped at ~107 GB/s instead of
~149 GB/s on P5EN (16×EFA 200Gbps).

Also convert the initiator from single-threaded to multi-threaded
(--threads flag) and print the actual P2P handshake address.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(efa): add p6-b300 bandwidth results (752 GB/s GPU, 230 GB/s CPU)

- GPU-to-GPU peak 752 GB/s write / 713 GB/s read at ~94% line rate
  (16×400 Gbps = 800 GB/s theoretical)
- CPU-to-CPU peak 230 GB/s, DRAM-limited on Xeon 8559C
  (NUMA-0 NICs 90 Gbps vs NUMA-1 NICs 53 Gbps)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(rust): customer_pattern sample for per-NUMA multi-MR registration

Adds a Rust binary mirroring the customer's EFA usage pattern: target
registers many MRs per NUMA (e.g. 16 NICs x N x 10GB via cpu:<numa>
locations); initiator reads/writes a specific (numa, buffer_index)
tuple, using --source-numa to pick which local NIC set is exercised.

Also makes rust/build.rs robust against non-default transfer_engine
build configurations: etcd-cpp-api is opt-in via MOONCAKE_WITH_ETCD=1,
CUDA linking is opt-in via MOONCAKE_WITH_CUDA=1 with CUDART_LIB_DIR
override, and libbase.a + libasio.so + libfabric paths are picked up
whether the repo uses the standalone or top-level CMake layout.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(rust): drop customer_pattern sample from upstream

Revert Cargo.toml [[bin]] additions and remove the bench demo source so
the public tree no longer ships it. Keep it gitignored locally so it can
be iterated on without accidental re-adds.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(efa): eager endpoint warmup for segments to remove first-batch stall

libfabric FI_EP_RDM endpoints resolve peer addresses lazily — the first
submitTransfer() to a new segment serializes fi_av_insert + handshake over
every (local_ctx, peer_nic) pair. On 16-NIC instances this is a ~4 s stall
on the first 100 × 0.5 MB batch (measured on p6-B300).

Add EfaTransport::warmupSegment(name) that pre-connects all pairs
concurrently via std::async, plus C wrapper warmupEfaSegment() (guarded by
USE_EFA) and Rust binding TransferEngine::warmup_efa_segment(). Idempotent,
safe to re-run after metadata changes. RDMA/TCP paths untouched.

Measured on p6-B300 (16 × 16 endpoints, dual-NUMA initiator):
  first-batch: 4043 ms -> 13.5 ms (~300x)
  steady-state: 141 GB/s -> 230 GB/s

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(efa): enable auto-split when max_mr_size is not configured

When MC_EFA_MAX_MR_SIZE is unset, max_mr was 0 and chunk_limit collapsed
to 0, bypassing the PTE-aware split entirely. Large 4KB-paged buffers
then hit the per-NIC PTE ceiling at registration time.

Fall back to pte_limit so splitting kicks in based on the PTE budget
alone when no explicit max_mr_size is provided.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* style: apply clang-format to EFA transport/tests and PEP8 to kvcache bench

Pure formatting changes to satisfy CI format hook (clang-format-20) and
address Gemini review comment on kvcache_prefix_bench.py indentation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Ubuntu <ubuntu@ip-172-31-13-185.us-east-2.compute.internal>
Co-authored-by: whn09 <whn09@github.com>
2026-04-20 15:04:49 +08:00
王鹤男 a6cbc1a417
[TE] Add fi_read support, endpoint LRU eviction, and multi-NIC striping for EFA transport (#1821)
* fix(efa): add fi_read support and endpoint eviction to EFA transport

1. EFA submitPostSend() now branches on slice->opcode to call fi_read
   or fi_write, matching RDMA transport behavior. Previously only
   fi_write was implemented, breaking remote-read workloads on EFA.

2. EfaEndpointStore now tracks endpoint activity and evicts stale
   endpoints when approaching AV capacity. This prevents AV exhaustion
   in long-running services communicating with many transient peers.
   - Endpoints marked active on access, inactive on set_active(false)
   - Configurable inactive timeout (default 5 min)
   - evictStale() removes endpoints inactive beyond timeout
   - removeDisconnected() cleans up broken connections
   - Eviction triggered automatically in getOrInsert() at capacity

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* perf(efa): eliminate per-slice overhead with NIC-count-based striping

Replace fixed 64KB slicing with NIC-count-based chunking in EFA
submitTransferTask. For large transfers (>128KB), creates one slice
per active NIC instead of thousands of small slices, dramatically
reducing spinlock, atomic, and allocation overhead.

- Large transfers: stripe across all active NICs (1 chunk per NIC)
- Small transfers: single slice on one NIC, no sub-slicing
- Fallback: per-slice retry for edge cases (unregistered memory)

Example: 240MB transfer on 32 NICs now creates 32 slices vs 3840,
matching NIXL approach of one fi_write per rail per descriptor.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(efa): add FI_MR_HMEM to mr_mode hints for GPU memory registration

EFA provider requires FI_MR_HMEM in domain mr_mode hints to support
heterogeneous (GPU) memory registration via fi_mr_reg. Without this
flag, fi_mr_reg fails with EFAULT (Bad address) when registering
CUDA device memory buffers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(efa): apply clang-format-20 formatting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(efa): restore lost changes from merge — endpoint eviction, batched WR, docs

Restores 5 commits that were lost during the upstream merge:
- AV entry removal on disconnect to prevent target degradation
- Endpoint reuse for same physical peer (normalizeNicPath)
- Batched WR submission in submitPostSend
- Pre-resolved remote peer info for striped transfers
- Documentation: GPU-to-GPU (313 GB/s), CPU-to-CPU (222 GB/s) benchmarks,
  CPU-only build instructions, B300/P5 instance types

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(efa): use dependencies.sh for build deps, add EFA-specific extras

Replace manual package list with dependencies.sh script reference.
Add libgflags-dev as EFA-specific extra dependency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(efa): add tip to use CUDA_VISIBLE_DEVICES for CPU-to-CPU benchmarks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(efa): add DLAMI troubleshooting for CUDA env and Python activation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(efa): add LIBRARY_PATH for CUDA libs, remove unneeded CUDAToolkit_ROOT

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(efa): add block_size=1MB to all benchmark configurations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(efa): merge clone step into build dependencies section

dependencies.sh already runs git submodule update --init --recursive,
so the separate clone section was redundant. Move git clone into the
Prerequisites section and renumber build steps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(efa): add SGLang usage, Docker troubleshooting, reorder sections

- Move Usage with vLLM/SGLang after benchmark results (was too early)
- Add Usage with SGLang section (EFA patch, env vars, Docker example)
- Add libfabric version mismatch in Docker troubleshooting
- Reorder p5en results: GPU-to-GPU before CPU-to-CPU (consistent with B200)
- Update p5en single-instance CPU results: Write 179 GB/s, Read 185 GB/s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(efa): use GlobalConfig max_ep_per_ctx (65536) as default, round-robin CQ assignment

- Change EfaEndpointStore and EfaContext::construct default max_endpoints
  from 256 to 65536, consistent with GlobalConfig.max_ep_per_ctx
- Add round-robin CQ assignment (nextCq) for new endpoints instead of
  always using cq_list_[0], distributing load across CQs
- Pass CQ outstanding counter directly to endpoint construct

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(efa): clang-format, move striping threshold to GlobalConfig

- Run clang-format on all EFA transport files and common.h
- Move MC_EFA_STRIPING_THRESHOLD from inline std::getenv to GlobalConfig
  mechanism (loaded centrally in loadGlobalConfig), per reviewer feedback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* ci: add 'wqs' to typos ignore list (EFA API function name)

efadv_query_qp_wqs is a libfabric EFA API symbol, not a typo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(efa): add per-transfer latency benchmark script

Automated script that measures single-transfer latency across block sizes
by SSHing into target/initiator nodes and running transfer_engine_bench
with threads=1, batch_size=1.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(efa): add --threads and --batch_size args to latency bench script

Allow configurable threads/batch_size for multi-thread bandwidth scaling tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(efa): add --env flag to pass env vars to remote bench via SSH

Allows setting MC_EFA_STRIPING_THRESHOLD and other env vars on the
remote initiator without manual SSH config.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* ci: fix typos check by adding wqs to extend-words

The extend-ignore-words key is not recognized by typos v1.30.2 used
in CI. Add wqs (EFA API function name efadv_query_qp_wqs) to the
[default.extend-words] section which is the correct format.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: revert formatting-only changes in common.h

Revert pointer/reference style changes (`&`/`*` placement) that were
introduced by clang-format but are unnecessary for this PR. Keep only
the normalizeNicPath() function addition.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(efa): clarify that MC_SLICE_SIZE does not apply to EFA transport

EFA transport uses NIC-count-based striping (since commit 84d7dc5),
not fixed-size slicing. block_size directly determines per fi_write/
fi_read size for transfers below the striping threshold. Update docs
to reflect this and correct outdated tuning advice.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(efa): address review issues - nextCq guard, error path double-free, GPU MR registration

1. nextCq(): add empty guard to prevent division-by-zero when cq_list_ is empty
2. submitTransferTask error paths: replace getSliceCache().deallocate(s) with
   s->markFailed() to prevent double-free (TransferTask destructor also deallocates)
   and ensure tasks complete with FAILED status instead of hanging
3. registerMemoryRegionInternal(): use fi_mr_regattr() with explicit FI_HMEM_CUDA
   iface and device ordinal for GPU memory, since EFA provider fi_mr_reg()
   hardcodes iface=FI_HMEM_SYSTEM
4. Make total_bytes updates atomic (__sync_fetch_and_add) for thread safety

Tested: unit tests (5/5), cross-node GPU benchmark (write 250 GB/s, read 269 GB/s)
on p5en.48xlarge.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(efa): apply clang-format to efa_context.cpp

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: EC2 Default User <ec2-user@ip-172-31-8-212.us-west-1.compute.internal>
Co-authored-by: whn09 <whn09@github.com>
2026-04-17 01:30:39 +08:00
ykwd 9ce5d25292
update docs (#1905)
Co-authored-by: Ke Yang <yangke@approaching.ai>
2026-04-16 23:23:11 +08:00
Chuang Zhang 3a69fa4b4d
[TE] Enabling UB Transport on the Kunpeng SuperNode Phase 2 (#1855) 2026-04-15 00:15:34 +08:00
fatSheep 7d0978b9ca
[Store] Add Upsert API for in-place object updates (#1662)
Co-authored-by: fatSheep <tzh2005t@gmail.com>
2026-04-03 10:24:37 +08:00
Mike Chen 8f39661a31
[DOC] add missing steps to efa transport readme (#1759)
---------

Co-authored-by: Bobby <bobby@Bobbys-MacBook-Air.local>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-28 11:31:28 +08:00
Yufeng He 4c19802458
[Store] Add hard pin mechanism for eviction-protected objects (#1728)
* [Store] Add hard pin mechanism for eviction-protected objects

Objects created with ReplicateConfig.with_hard_pin=true are never
evicted by the eviction policy, providing guaranteed persistence
for model weights in RL and model management workloads.

Changes:
- ReplicateConfig: add with_hard_pin field (default false)
- ObjectMetadata: add hard_pinned boolean, set at creation via PutStart
- BatchEvict: skip hard-pinned objects in all eviction passes
- Serialization: persist hard_pinned in snapshots (backward compatible
  with old format that lacks the field)
- Tests: verify hard-pinned objects survive eviction, coexist with
  soft pin, and can still be explicitly removed
2026-03-25 17:41:40 +08:00
zhangzuo21 f40407eb59
[Docs] Add SSD offload documentation (#1647) 2026-03-19 15:37:59 +08:00
1180300720 22ecbd794e
[CI] update ascend ci and docs (#1683)
Co-authored-by: ZhaoBaiwei <zhaobaiwei@huawei.com>
2026-03-17 20:34:42 +08:00
yizheng 5fe8e21e7c
[Store] Implement Metadata Persistence and Recovery for Master Service (#1431) 2026-03-02 11:20:33 +08:00
fatSheep 9e4e9490b2
[Doc]: add allocation strategy documentation with user guidance (#1577)
* docs: add allocation strategy documentation with user guidance

Document the three built-in allocation strategies (random, free_ratio_first, cxl)
with a user-facing comparison table, selection guidance, and detailed descriptions.

* Update docs/source/design/mooncake-store.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Update docs/source/design/mooncake-store.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: fatSheep <tzh2005t@gmail.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-02 10:50:31 +08:00
Feng Ren c0a1e6570d
[TE] Implement TCP connection pooling to reduce connection overhead (#1508)
* [TE] Implement TCP connection pooling to reduce connection overhead

* fix correctness

* Code reformat

* Fix according to review comments

* Retrigger CI

* Fix connection pool issues

* default disable connection pool to ensure stability
2026-02-27 09:56:34 +08:00
ascend-direct-dev 3e67c9e443
[TE] change ascend direct transport docs & fix async transfer disconnect bug 2026-02-12 14:20:02 +08:00
youxiao 38d2fbb18b change ascend direct transport docs 2026-02-11 16:53:55 +08:00
王鹤男 3cdbbdc6d0
[TE] Support TCP fallback in EFA build and improve EFA documentation (#1523)
When building with USE_EFA=ON, auto_discover is disabled to prevent
RDMA transport installation (QP creation fails on EFA devices). This
means TCP transport is also not installed automatically. Add explicit
TCP transport installation for non-EFA protocols in the EFA build path.

Documentation changes:
- build.md: Add USE_EFA option and clarify USE_CUDA default/purpose
- supported-protocols.md: Add EFA as a supported protocol
- efa_transport.md: Add USE_CUDA=ON to build command, document GPU
  memory requirement

Co-authored-by: whn09 <whn09@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Teng Ma <teng-ma@linux.alibaba.com>
2026-02-11 10:50:35 +08:00
yejj 8c60e6c4cb
[docs] add conductor indexer api design doc (#1416)
* add indexer api design doc

* remove some api & add explain info for tiered storage

* rename tired storage level name

* add overview architecture

* define the input of  indexer kvevent

* add example for indexer api output

* fix some issue from code reviews

* add explain for different medium

* delete the confusing note

* add more Introduction for indexer output value

* change some code based on the code review

* use medium name directly

* fix some format problem

* support multi-tenant & cache salt and  rename engine_name
2026-02-10 00:06:52 +08:00
王鹤男 4136d2b73b
[TE] Add AWS EFA transport using libfabric (#1509)
* [TE] Add AWS EFA transport using libfabric

Add EfaTransport as a new transport backend for AWS Elastic Fabric
Adapter (EFA) devices.  EFA exposes RDMA-like NICs but does not support
the full ibverbs QP API, so this transport uses libfabric's FI_EP_RDM
(Reliable Datagram Message) endpoint type instead.

Architecture (per EFA device):
  EfaTransport → EfaContext → EfaEndPoint
  - EfaContext: owns fabric/domain/AV/CQ/MR resources
  - EfaEndPoint: one RDM endpoint per peer, with address-vector addressing
  - Dedicated CQ poller thread per device for responsive completion draining

Key design decisions:
  - FI_THREAD_SAFE requested from provider; per-endpoint spinlock on
    fi_write as safety net for concurrent submission threads
  - Atomic CAS reservation of CQ and WR capacity before posting fi_write
    to prevent CQ overflow under high concurrency
  - CQ error path drains all queued errors (fi_cq_readerr loop) before
    returning, per libfabric semantics
  - Retry-with-backoff on CQ/WR full instead of immediate slice failure
  - Thread-safe endpoint creation via atomic getOrInsert to prevent
    duplicate endpoints for the same peer
  - Handshake exchanges EFA endpoint addresses via dedicated efa_addr
    field in HandShakeDesc

Build: cmake -DUSE_EFA=ON (requires libfabric from AWS EFA installer)
Tested on p6-b200.48xlarge (8 EFA devices, 8×400 Gbps): 59.72 GB/s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [TE] Add EFA unit tests and bench tool support

Add efa_transport_test with 5 test cases:
  - InstallTransport: verify EFA transport installation
  - LoopbackWrite: basic loopback write operation
  - WriteAndRead: write then read with data integrity check
  - MultiWrite: batch write (16 requests)
  - StressMultipleBatches: stress test (20 batches × 8 requests)

Add --protocol=efa support to transfer_engine_bench with manual
topology discovery (EFA needs explicit discover() since
TransferEngine(false) skips auto-discovery).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [Docs] Add EFA transport documentation

Add comprehensive EFA transport documentation covering:
  - Prerequisites and build instructions
  - Usage with vLLM (prefill/decode disaggregation)
  - Unit test descriptions and environment variables
  - Benchmark results on p6-b200.48xlarge: 59.72 GB/s (EFA) vs
    9.5 GB/s (TCP iperf3) vs 0.11 GB/s (Mooncake TCP transport)
  - EFA vs RoCE RDMA comparison table
  - Thread safety design notes
  - Troubleshooting guide

Add EfaTransport to the transfer-engine index toctree and supported
transport lists.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [TE] Address PR review: ifdef EFA fields, use find_package for libfabric

- Wrap efa_addr in HandShakeDesc with #ifdef USE_EFA in transfer_metadata.h
- Wrap efa_addr serialization/deserialization with #ifdef USE_EFA in transfer_metadata.cpp
- Replace hardcoded /opt/amazon/efa paths with find_path/find_library in common.cmake
- Remove redundant hardcoded EFA paths from all CMakeLists.txt files
- Fix git clone URL in efa-transport.md to use official kvcache-ai/Mooncake repo

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [Docs] Update EFA benchmark results with tuned parameters (170 GB/s)

Update benchmark documentation with comprehensive parameter tuning results
from cross-machine testing on p6-b200.48xlarge instances. Key finding:
MC_SLICE_SIZE=262144 nearly doubles EFA throughput from ~70 to ~170 GB/s,
reaching 88% of RoCE RDMA performance.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix clang-format violation in transfer_metadata.h

Remove extra space before comment on efa_addr field to satisfy
clang-format-20 style check.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [Docs] Add EFA latency benchmark script, rename efa doc to underscore

- Add efa_latency_bench.py: automated benchmark script that measures
  EFA throughput for tuned/default configs via SSH and plots
  Latency vs Cache Size chart
- Add efa_latency_bench.png: benchmark results chart
- Rename efa-transport.md -> efa_transport.md to match naming
  convention of other transport docs (ascend_transport.md, etc.)
- Update toctree reference in index.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Ubuntu <ubuntu@ip-172-31-25-79.us-east-2.compute.internal>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Ubuntu <ubuntu@ip-172-31-22-204.us-east-2.compute.internal>
2026-02-08 11:41:17 +08:00
tang c724318217
[Store][Feature] copy and move client support (#1364)
* [Store]: add task executor feature with unit and executor test

Signed-off-by: Vincent Gao <vincentbo@linux.alibaba.com>

* [Store]: add some optimizations to task executor

Refactor the task_executor into the client_service and add a
task structure on the client side. Additionally, remove the
existence check in the execute function;
only retrying should be performed if replica allocation fails.

Signed-off-by: Vincent Gao <vincentbo@linux.alibaba.com>

* [Store]: get source replica from copyStart or moveStart api

* [Store]: call move or copy end if the target replica already exist to complete the replication task

* [Store]: use the max_retry_attempts in master side

* [Store]: add client integration test and set default max_retry_attempts to 10

* [Doc] update task api introduction

Signed-off-by: Vincent Gao <vincentbo@linux.alibaba.com>

* [Store] Set copy and move as private methods

Signed-off-by: Vincent Gao <vincentbo@linux.alibaba.com>

* [Doc]: change the default task max_retry_attempts to 10

* [Doc]: fix some description error

* [Store]: allocate the buffer size to be a multiple of 16MB

* [Store]: validate the replica is in local and directly construct slices from replica buffer address instead of copy the data to local buffer

* [Store]: change the validate logic to directly use transfer engine endpoint or local_hostname_.

* [Store] add e2e ci test for copy and move api

* [Store] refactor the client move and copy function

* [Store] fix the e2e test

* [Store] remove unused code

* [Store] add source field when build replica copy payload in the task_manager_test

* [Store] rename back to snake case for split_into_slices function and also remove hard code for client poll count

* [Store] revert mis deleted field when resolve conflicts

* [Store] change test to validate the real behaviour

* [Store] change the default task fetch size to 16

* [Doc]: change the replica copy/move sequence diagram

* [Store] add new split_into_slice method

* [Store] change the real client to use split_to_slice with buffer handle parameters

---------

Signed-off-by: Vincent Gao <vincentbo@linux.alibaba.com>
Co-authored-by: Vincent Gao <vincentbo@linux.alibaba.com>
2026-02-06 19:02:02 +08:00
ZhangCheng 01d1c6a8b3
[TE] Add auto-connect feature controlled by config and environment variable (#1482)
Co-authored-by: zhangcheng <zhangcheng299@huawei.com>
2026-02-05 14:07:56 +08:00
fatSheep 17b9df8fb8
[Docs]: Add TENT C++ API reference (#1488)
* docs: Add TENT C++ API reference and integrate into documentation navigation

* Update docs/source/design/tent/cpp-api.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Delete trailing asterisks

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-02-05 13:41:02 +08:00
Feng Ren 5b9243280b
[TENT] Add RDMA-based notification (#1460)
* [TENT] Add RDMA Notification

* Fix notify

* Fix issues

* reformat

* Optimize performance

* Apply suggested changes

* remove duplicated code
2026-02-02 15:13:39 +08:00
fatSheep 9b242111aa
[Doc] improve Transfer Engine C++ API Reference (#1467)
* [Doc] improve Transfer Engine C++ API Reference

* Update docs/source/design/transfer-engine/cpp-api.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Update docs/source/design/transfer-engine/cpp-api.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Update docs/source/design/transfer-engine/index.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Update docs/source/design/transfer-engine/cpp-api.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-02-02 15:12:05 +08:00
Lewis 6f6c95e480
Intra-Node NVLink related Docs modification (#1424)
---------

Co-authored-by: 百麒 <yaozhong.lyz@alibaba-inc.com>
Co-authored-by: Teng Ma <teng-ma@linux.alibaba.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-01-22 22:52:06 +08:00
herrluk 619b03a954
[TE] Add configurable handshake max length via MC_HANDSHAKE_MAX_LENGTH (#1392)
Add MC_HANDSHAKE_MAX_LENGTH environment variable to configure the maximum
handshake message length in P2P mode.

## Problem

When using P2P handshake mode with a single RDMA instance that registers
many memory buffers (>10,000), the serialized segment metadata JSON can
exceed the hardcoded 1MB limit, causing handshake failures with error:
"readString: too large length from socket: <length>"

Each registered buffer adds ~96 bytes to the JSON payload:
- 1,000 buffers ≈ 94KB
- 5,000 buffers ≈ 469KB
- 10,000 buffers ≈ 938KB (near 1MB limit)
- 15,000 buffers ≈ 1.37MB (exceeds limit)

## Solution

- Add getHandshakeMaxLength() function that reads MC_HANDSHAKE_MAX_LENGTH
- Value is in bytes, valid range: 1MB to 128MB
- Default remains 1MB (1048576 bytes) for backward compatibility
- Logs custom value when set, warns on invalid values

## Usage

```bash
# Set to 4MB to support ~40,000 buffers
export MC_HANDSHAKE_MAX_LENGTH=4194304
```
2026-01-22 14:15:22 +08:00
Lewis c9d64c91c4
[TE] Nvlink intraNode Transport isolation (#1341)
* Add early mem backend detection method in NVLINK_allocator

Add early detection method for sglang NVLINK_allocator to avoid CuMemCreate

Use enumerate type to indicate mem backend type

format check use pre-commit

* Change enumerate type in allocator.py for different mem backend

* Isolate nvlink intraNode transport from nvlink_transport and modify corresponding transfer_engine_bench

* IntraNode transport isolation to be compatible with SGlang

* Modify the code style using pre-commit check

* isolate intraNode nvlink from previous nvlink_transport

* [TE] Revert to previous nvlink_transport

* Delete extra log and refine the code format

* Discard revert due to new related PR has been submitted

* Change the Code format to align with main branch

* Change to clang-format

* Modify transfer_engine_bench to be compatible with protocol --nvlink_intra

* Delete useless function in intranode_nvlink.cpp

* Used for rerun CI

* Modify the intraNode isolation to be compatible with transfer_bench and transfer_engine_impl

* isolate intraNode header file from mnnvl.h

* Delete specific instaince type for intraNode

---------

Co-authored-by: 百麒 <yaozhong.lyz@alibaba-inc.com>
2026-01-22 10:17:12 +08:00
Stary abb429f935
[TENT] Add Metrics System with HTTP Server and Prometheus Integration (#1355)
* feat(metrics): add TENT metrics system with HTTP server and Prometheus
integration

- Add comprehensive metrics system based on yalantinglibs for monitoring data
transfer performance
- Implement HTTP server with endpoints for Prometheus, JSON, and human-readable
metrics
- Add compile-time and runtime performance optimization with zero-overhead when
disabled
- Integrate metrics into TransferEngine with automatic latency tracking
- Add configuration loader supporting config files and environment variables
- Include example application demonstrating metrics usage
- Add documentation for metrics system configuration and usage

Signed-off-by: staryxchen <staryxchen@tencent.com>

* Update docs/source/design/tent/metrics.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* refactor(metrics): simplify config loading with explicit priority

- Replace indirect environment config loading with direct parsing
- Implement clear priority: file config > environment variables > defaults
- Add validation for environment variable values
- Remove redundant default value comparisons

Signed-off-by: staryxchen <staryxchen@tencent.com>

* refactor(transfer_engine): extract metrics recording logic into dedicated method

- Add recordTaskCompletionMetrics method to TransferEngineImpl class
- Replace duplicate metrics recording code in getTransferStatus methods with
calls to new method
- Centralize task completion metrics logic for better maintainability

Signed-off-by: staryxchen <staryxchen@tencent.com>

* build(metrics): improve yalantinglibs dependency handling

- Change warning to fatal error when TENT_METRICS_ENABLED is ON but
yalantinglibs is missing
- Provide clearer warning message when metrics are disabled

Signed-off-by: staryxchen <staryxchen@tencent.com>

* refactor(metrics): replace manual JSON construction with nlohmann/json library

- Use nlohmann/json for cleaner and more maintainable JSON serialization
- Remove manual string stream manipulation and formatting
- Improve code readability and reduce error-prone manual concatenation

Signed-off-by: staryxchen <staryxchen@tencent.com>

* style: reformat code with clang-format

Signed-off-by: staryxchen <staryxchen@tencent.com>

* refactor(config): centralize parsing utilities in ConfigHelper

- Move parsing functions from MetricsConfigLoader to ConfigHelper
- Add applyEnvironmentOverrides method to reduce code duplication
- Update includes and comments to reflect new structure

Signed-off-by: staryxchen <staryxchen@tencent.com>

* test: add unit tests for metrics config loader and reorganize test structure

- Move examples directory to tests directory in CMakeLists.txt
- Add comprehensive unit tests for MetricsConfigLoader functionality
- Include tests for config parsing, environment variable loading, and validation
- Rename and relocate tent_metrics_example.cpp to tests directory

Signed-off-by: staryxchen <staryxchen@tencent.com>

* style: reformat code lines for better readability

Signed-off-by: staryxchen <staryxchen@tencent.com>

* fix(build): remove redundant Asio dependency from metrics CMakeLists

- Remove Asio dependency search and linking as yalantinglibs bundles it
internally
- Add clarifying comment about bundled Asio in yalantinglibs

Signed-off-by: staryxchen <staryxchen@tencent.com>

---------

Signed-off-by: staryxchen <staryxchen@tencent.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-01-12 16:25:10 +08:00
EkiRui e0ddd91629
[Store] add HugePage support (#1300)
* [Store] add HugePage support

Co-authored-by: Teng Ma <sima.mt@alibaba-inc.com>
Signed-off-by: Xingrui Yi <yixingrui@linux.alibaba.com>

* doc: add huge page env introduction

Signed-off-by: Xingrui Yi <yixingrui@linux.alibaba.com>

---------

Signed-off-by: Xingrui Yi <yixingrui@linux.alibaba.com>
Co-authored-by: Teng Ma <sima.mt@alibaba-inc.com>
2025-12-30 16:12:40 +08:00
EkiRui 70488aae3f
[Store]doc: add dummy client support for SGLang hicache integration (#1299)
Signed-off-by: Xingrui Yi <yixingrui@linux.alibaba.com>
2025-12-29 16:50:26 +08:00
fatSheep dc40512726
[Doc] Fix transfer engine doc image paths (#1295)
* fix transfer engine doc image paths
2025-12-28 01:16:47 +08:00
ascend-direct-dev a6827f2bd4
mooncake store support ascend fabric mem (#1170)
Co-authored-by: youxiao <youxiao@huawei.com>
2025-12-28 01:14:44 +08:00
Harold Huang f21e69511c
[TE] add MC_FORCE_HCA environment variable to force use rdma (#1259)
* add MC_FORCE_HCA environment variable to force use rdma

* Updater for better readability

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* fix clang-format problem

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-12-23 15:25:12 +08:00
Feng Ren e8db9e54cf
[TE] Add TENT codebase to main (Phase 1: structural import) (#1213)
* [TE] Add TENT to main branch: Phase 1

* Fix CI issues

* Apply suggestions from code review

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Fix build bug

* Update code format

* Fix code format issue

* disable building Mooncake TENT by default

* Code reformat

* Revise benchmark code and add docs

* format bench code

* Retrigger

* Update Python APIs

* Fix bugs

* Register memory in parallel

* Fix wheel packing

* Format fix

* reformat

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-12-22 19:22:13 +08:00
Xun Sun 832ae19492
[EP] Implement elastic scaling up (#1173) 2025-12-22 14:10:40 +08:00
Stary 87c14b8c97
feat(TE): Add MC_ENABLE_PARALLEL_REG_MR Option (#1238) 2025-12-20 19:19:24 +08:00
Anatolii Rozanov 38bd84f3c3
[TE]: Add HIP transport for AMD GPUs support (#1208)
* [TE]: Add HIP transport for AMD GPUs support

Forked from nvlink_transport and adapted for HIP/AMD GPUs.

* [TE/HIP] Addressed review comments

* [TE] Move NVLINK and HIP common functions to common files

* [TE] Fix incorrect length assignment in relocateSharedMemoryAddress

Use entry.length instead of length parameter when storing OpenedShmEntry.
The length parameter represents the requested transfer length, while
entry.length represents the actual buffer's full length, which is the
correct value to store and is consistent with openShareableHandle usage.
2025-12-16 19:27:47 +08:00
早些年 22e6ad750b
[TE] feat: add PCIe Relaxed Ordering (RO) support and RDMA traffic class (… (#1076)
* add PCIe Relaxed Ordering (RO) support.

* fix: add env variable to control Relaxed Ordering (RO)

* refactor: simplify logic in mooncake-transfer-engine/src/transport/rdma_transport/rdma_transport.cpp

Co-authored-by: Teng Ma <teng-ma@linux.alibaba.com>

* fix(RO): set default value to 0

* fix(ci): resolve compilation error in PR build

* Supplement guidance documents

* refactor: remove dlopen, use dlsym alone for symbol checking

---------

Co-authored-by: Teng Ma <teng-ma@linux.alibaba.com>
2025-12-15 18:40:04 +08:00
Jianxin 38138f9136
[Doc] Hotfix: Remove duplicate docs (#1211) 2025-12-15 14:17:09 +08:00
Jianxin df201882b2
[Doc] Merge doc to docs (#1153)
* merge doc/en/ to docs/

* move chinese documents to an archive directory
2025-12-15 12:08:49 +08:00
Vincent-Bo-ali 024b695a8d
[Store] feat: Add BatchReplicaClear API for manual cache cleanup (#1191)
* [Store] feat: Add BatchReplicaClear API for manual cache cleanup

Implement the `BatchReplicaClear` API to allow clients to manually clear
cached object replicas. This feature enables explicit storage management
by deleting replicas for specified keys. The implementation is end-to-end,
from the client to the master service.

Signed-off-by: Vincent Gao <vincentbo@linux.alibaba.com>

* [Store] feat: Fix BatchReplicaClear monitor issues

Fixed issues with monitoring metrics not being updated and function naming.
Fix the issue of unclear descriptions in the file.

Signed-off-by: Vincent Gao <vincentbo@linux.alibaba.com>

---------

Signed-off-by: Vincent Gao <vincentbo@linux.alibaba.com>
2025-12-12 23:08:48 +08:00