Skip to content

operatorx: gemm + moe on NVIDIA and AMD - #3452

Merged
hbarclay merged 82 commits into
mainfrom
hbarclay/operatorx
Oct 23, 2026
Merged

hbarclay merged 82 commits into
mainfrom
hbarclay/operatorx

Conversation

@hbarclay

@hbarclay hbarclay commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator

OperatorX measures single ops (a GEMM, one MoE layer) on NVIDIA and AMD. It runs them through the same framework layers InferenceX serves with, so the kernel it times is the kernel real inference uses. This PR replaces the prototype under experimental/operatorx/ with that version, adds the collection methodology, and connects the sweep to the OperatorX database.

Scope

  • Ops: only gemm and moe for now.

    • Attention, collectives, moe_gemm, moe_forward, moe_layer, the other NVIDIA backends, the TPU and Trainium runners, and the scripts/inferencex_testlist generator are removed. Ops and platforms will come back one at a time.

    • gemm (ops/gemm.py): activation a [M, K] and weight b [N, K]. Each is an operand descriptor {"dtype", "scale"?, "scale2"?, "symmetric"?}.

      • scale is {"dtype", "static", "group": [rows, cols]}, and -1 spans a dimension.
      • So [-1,-1] is per-tensor, [1,-1] per-token, [-1,1] per-channel, [1,g] groups of g along K, and [r,c] 2-D blocks.
    • moe (ops/moe.py): one MoE layer from the router GEMM to the combined output. It has:

      • tokens and hidden;
      • experts: count, top-k, intermediate size, optional bias / latent / zero experts, and the operand descriptors a1 (input), w1 (fused gate/up weight), w2 (down weight) and a2 (intermediate activation), named after vLLM's FusedMoEQuantConfig slots;
      • router: gate dtype, scoring, selection, bias, renormalize, scale;
      • activation, optional shared experts, and a routing distribution (natural / balanced / zipf / single_hot).

      Kernels, dispatch, fusion and streams are the backend's choice.

    • Every case says where it comes from: sources lists one <checkpoint>/<role> per layer that runs it, e.g. deepseek-ai/DeepSeek-V4-Pro/attn.wq_b or zai-org/GLM-5-FP8/mlp.

      • A shape shared by several models, or by several layers of one model, lists every pair, so each role stays tied to its model. The role is what follows the last /.
      • DeepSeek-V4 roles come from the checkpoints' own weight maps under vLLM's TP sharding and fusions. That covers the indexer, compressor, router, mHC and head (lm_head) shapes.
      • It's metadata and doesn't change what's measured.
  • Backends:

    • vllm gemm (NVIDIA, AMD; runners/common/vllm/linear.py).
      • Builds vLLM's ReplicatedLinear under the quant config the descriptors imply, loads synthetic checkpoint-format weights, and runs process_weights_after_loading. vLLM then does its own activation quantization, repacking and kernel selection.
      • Emulation-only paths are reported unsupported. So is a quantized layer that comes out unquantized.
    • vllm moe (runners/common/vllm/moe.py): vLLM's GateLinear router, FusedMoEFactory experts and shared-expert MLP, wired as vLLM's model blocks wire them. Covers DeepSeek-V4 FP4 experts and hash routing, Kimi-K3 latent experts, Qwen's shared-expert gate, and forced expert loads.
    • torch (AMD): hipBLASLt bf16 and per-tensor fp8.
  • Testlists:

    Testlist Cases What
    gemm.json 5,416 InferenceX matrix shapes under each checkpoint's per-layer quant scheme
    gemm_serving_{8k1k,all}_min.json 1,505 / 8,099 DeepSeek-V4-architecture shapes; sources is DSv4-Pro where the shape is one of its projections, else []
    gemm_perf.json 11 BF16 smoke list
    moe_small.json 62 One full-size MoE layer per InferenceX MoE checkpoint scheme (32 checkpoints) at tokens=1; one layer per family swept at 8/64/512/2048 tokens; DeepSeek-R1 / Qwen3.5 FP8 under each expert-load distribution

    gpt-oss is left out of moe_small for now. Its biased MXFP4 experts don't go through vLLM's mxfp4 method cleanly here yet.

Measurement

  • GPU timing:
    • Warmup has a wall-clock floor.
    • A GPU spin runs ahead of the timed loop, so launch overhead is excluded.
    • The cache is flushed before every iteration; the result is the median of 10.
  • Telemetry (runners/common/telemetry.py):
    • NVML / amdsmi record clocks, power, temperatures and throttle reasons while each op runs.
    • Capped attempts are retried with growing inter-kernel sleeps.
  • Profiling (runners/common/profiling.py, runners/common/trace.py):
    • A torch.profiler replay attaches a per-kernel breakdown (metrics.profile).
    • A platform-independent trace module (trace.py) with a small adapter per platform (CUDA/ROCm today).
  • Counters mode: one marked replay per op under Nsight Compute or rocprofv3. Counter files go under results/counters/, and latencies are perturbed.

CI (operatorx-sweep.yml)

  • Inputs:
    • runner: a cluster: label (cluster:h100-dgxc default, then h200-dgxc, b200-nscale, b300-dsxe, gb200-nv, gb300-nv, mi300x-amd, mi325x-amds, mi355x-amds);
    • backends, testlists, mode (timing | counters), world_sizes, chunk_size.
  • New last job trigger-ingest: sends InferenceX-app an ingest-operatorx repository_dispatch with the run id, as run-sweep.yml does for benchmark results. The app stores the run in the OperatorX database (SemiAnalysisAI/InferenceX-app, branch hbarclay/operatorx). A run with failed shards is stored too; its unrun cases read as missing.
  • Dispatched from hbarclay/operatorx:
    • gemm timing, 5,416 cases each: H200, B200, B300, MI300X, MI325X, MI355X.
    • moe_small: H200, B300, MI300X, MI325X, MI355X.
    • Counters mode: H200, B200, MI300X, MI325X, MI355X.
    • B300 counters needs Nsight Compute ≥ 2025.3 on the dsxe nodes.
    • MI355X moe_small reports a failure only because one shard is all-unsupported under --strict; its data is complete.
  • tests/test_ci.py passes (32).

🤖 Generated with Claude Code

@hbarclay
hbarclay requested a review from a team September 26, 2026 04:33
@hbarclay hbarclay changed the title operatorx: gemm + moe on NVIDIA, AMD, TPU and Trainium, measured in the serving framework's own layers operatorx: gemm + moe on NVIDIA and AMD, measured in the serving framework's own layers Sep 26, 2026

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beyond the inline findings, I also checked the AMD torch GEMM backend's fp8 unsupported-case handling (runners/amd/backends/torch.py) against the actual testlist data: none of the e4m3 entries in gemm.json, gemm_perf.json, or the gemm_serving_*_min.json lists use the static per-tensor scale format the backend supports — they're all block-scaled (group [128,128] etc.), which the backend correctly rejects as unsupported. So this is the backend's documented per-tensor-only scope matching the current data, not a regression introduced by this change.

Extended reasoning...

This PR rewrites the operatorx microbenchmark tool end to end (CI workflow, core op/backend framework, gemm/moe op specs, and every vendor runner backend for NVIDIA/AMD/TPU/Trainium); it touches CI dispatch/scheduling but no auth or crypto surface. Four confirmed findings are already queued as inline comments (a Trainium NEFF-selection fallback that silently degrades to noisy host timing, testlist entries that bypass schema validation entirely, a telemetry polling-thread leak on kernel fault, and an eager registry-digest lookup in ci.py's plan() that can fail a whole plan on one transient pruned-image error). I additionally verified, by grepping the regenerated gemm testlists for the static per-tensor fp8 scale shape the AMD torch backend accepts, that no current test case actually hits that accept path with a genuine per-tensor scheme — the backend's narrow fp8 support matches the shipped data rather than silently dropping real coverage.

Findings marked 🟡 are optional suggestions and need no follow-up push.

Comment thread operatorx/ops/moe.py Resolved
Comment thread operatorx/runners/common/telemetry.py Resolved
Comment thread experimental/operatorx/ci.py Resolved
@functionstackx

Copy link
Copy Markdown
Collaborator

Sorry, over the weekend, there was 2 major refactors to clean up the technical debt accumalated over the past 11 months of moving at the speed of light. We don't see any major refactors in the forthseeable future besides cleaning up AMD multinode AgentX pile of bash. As much, due to the refactors, u would need to ask your agent to rebase from remote main@latest. Thank you in advance for ur understanding

hbarclay and others added 21 commits October 22, 2026 13:15
…hodology

Dense GEMM only (grouped GEMM staged separately): serving/agentic/sim
testlists, vLLM dense backend (fp8 W8A8 cutlass, bf16, bf16xfp8
weight-only with per-call activation quant in the timed region, nvfp4
with unsupported guards), sglang dense fp8, cluster registration.

Measurement methodology (replaces the previous timing loop and the
experimental opt-in profiler): event timing with wall-clock warmup
floor, pre-enqueued launch-gap shield, full L2 flush before every timed
iteration, median of timed iters; per-op kernel decomposition via
torch.profiler attached to every result by default (OPERATORX_PROFILE=0
opts out); nvtx/roctx marker mode + optional cache flush for external
hardware-counter collection (counter-run latencies are never timing
ground truth).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Keep exactly what the current collections validated: the dense gemm op,
the NVIDIA vLLM backend, the AMD torch/hipBLASLt backend with the same
timing methodology as NVIDIA (warmup floor, launch-gap shield, per-iter
cache flush), shared profiling module, and one small serving testlist
(gemm_serving_8k1k_min). Everything else (attention, moe, collectives,
other backends/platforms/testlists) is removed here and will be re-added
incrementally on this structure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The keep condition compared against a literal 1, which modulo 1 never
matches, so keep-every-trace runs silently kept none.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Flush the full cache hierarchy before every profiling replay
(OPERATORX_PROFILE_FLUSH_MB now defaults to 512; 0 restores warm
back-to-back replays) and exclude the flush kernel from the per-kernel
decomposition by identity, reporting flush_kernels_excluded.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Generic TelemetryProvider interface sampling fine-grained clocks, power
and throttle events on a background thread during the timed loop; NVML
implementation for NVIDIA (poll + driver sample-ring drain) and amdsmi
for AMD (gpu_metrics table with hardware throttle_status), plus a no-op
fallback. Each result carries metrics.telemetry (clock/power min/p50/max,
throttle reasons, attempts). If actual capping is observed (throttle
reason active while SM clock sits below rated boost - the power-cap
governor bit at boost clock is normal DVFS and does not trigger), the op
is re-measured with exponentially increased inter-kernel sleeps, at most
OPERATORX_THROTTLE_RETRIES (default 3) retries, keeping the best-median
attempt. Also sizes the AMD flush buffer to the full cache hierarchy
(ROCm reports only the per-XCD L2 slice).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ping

- amd/backends/torch.py: drop the import of the removed attention runner
  (the module failed to import) and its attention impls.
- telemetry: read NVML driver history only from the attempt's start, not
  from provider creation; match the NVML/amdsmi device to the torch device
  by UUID/PCI address (both ignore *_VISIBLE_DEVICES); record op identity
  and attempt per sidecar line; move the throttle-retry loop into
  telemetry.measure() so both runners share it.
- profiling: remove the OPERATORX_PROFILE_METRICS counter pass (inert in
  the vLLM container); trim docstrings and comments across the runners.

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

Each telemetry sample is now a dict: SM/graphics/memory/video clocks,
average and instantaneous power, GPU and HBM temperature, pstate and
utilization on NVIDIA (plus the driver's 20 ms power history); gfx,
memory and SoC clocks, hotspot/HBM temperature and activity on AMD.
NVIDIA windows also record deltas of the cumulative per-reason throttle
and perf-limit time counters and energy; the driver advances those in
100 ms steps, so average power is derived only for windows >= 1 s.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…zation schema

The gemm op now names storage dtypes (bf16/e4m3/e2m1/int4) and quantization
(scale_a, scale_b, scale dtypes). The vllm backend (NVIDIA and AMD) builds a
ReplicatedLinear under the matching checkpoint quant config, runs
process_weights_after_loading and times layer(x), so vLLM selects the kernel;
the chosen kernels, parameter dtypes and vLLM env are recorded per op.
Images follow InferenceX's vLLM recipes; AMD enables AITER.

Serving testlists are rewritten to the DeepSeek-V4-Pro checkpoint schemes
(FP8 128x128 ue8m0 blocks; compressor/indexer projections bf16), same shapes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ole schemes

scripts/inferencex_testlist/schemes.py maps each InferenceX checkpoint and
layer role to the scheme vLLM runs (from config/quant configs and safetensors
headers). gemm.json is regenerated with the same (m, n, k) shapes; shapes the
current enumerator no longer reproduces take the schemes of the models whose
projections match them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
a / b are {dtype, scale: {dtype, static, group: [rows, cols]}, scale2?,
symmetric?}, mirroring vLLM's QuantKey / ScaleDesc / GroupShape, with groups
over A [M, K] and B [N, K]. This replaces the flat scale strings: arbitrary
block shapes (e.g. DeepSeek-V4.1-Flash 32x32), second-level scales (NVFP4)
and asymmetric formats are now expressible, and the vLLM backend derives the
checkpoint quant config from the descriptors instead of a lookup table.
Testlists are converted entry for entry; op hashing is JSON-based so nested
args hash.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
telemetry, profiling and the vLLM linear backend are used by more than one
platform runner; runners/ now holds only the platform packages and common/.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
scripts/ (submit_run, pull_containers, consolidate_results, the testlist
generators) stays local for now. README and CLUSTERS.md describe launching
the entry point directly; references to tooling outside this project are
removed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
scripts/ (submit_run.py and the rest) is upstream code used by the CI
workflow; it goes back unchanged, along with the README / CLUSTERS.md text
describing it. This PR's generator changes stay out of the tree.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Describes one MoE layer as math and data only: shape, routed experts (with
gemm operand descriptors for x / w13 / w2 / a2, optional biases, latent width,
zero experts), router (gate dtype, scoring, top-k / grouped / hash selection,
bias, renormalize, scale, weight-on-input), activation, optional shared
experts, and the routing distribution. Kernels, dispatch, shared-expert
execution and graph use are left to the backend. No backend yet.

Also: tests/conftest.py so each test file imports operatorx on its own.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ackend fixes

- BackendImpl.launcher(ctx) returns what the runner times and profiles. The
  vLLM backend replays a full CUDA graph captured at vLLM's next capture size
  (batch padded as vLLM pads it) up to its max capture size and runs larger
  batches eagerly, recording the choice in backend_meta.graph.
- profile gains per-replay span/busy/gap/overlap/streams and an op-relative
  kernel timeline (stream, start, duration), so gaps and concurrency are
  explicit.
- vLLM backend: enable the CUDA quant_fp8 op for block-scaled weights as
  VllmConfig does in serving; MXFP4 W4A4 through Quark OCP-MX (the config AMD
  MXFP4 checkpoints ship); allocation / device faults are errors, not
  'unsupported'; set input/output_size_per_partition like the parallel
  linears real models use.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An operand's optional 'input' (default bf16) is the dtype it arrives in. When
it differs from 'dtype' the op includes the quantization; when equal the
operand is pre-quantized and the op starts at the matmul. The AMD torch FP8
path multiplies pre-quantized operands and now says so; the vLLM backend takes
bf16 input only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…the EP group

The profiler replay now enqueues a spin after each flush (as the timing loop
does), so an eager op's timeline shows device time rather than host launch
gaps; the spin kernel is excluded from the breakdown. The vLLM context also
creates the size-1 expert-parallel group MoE layers need.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The backend launcher returns (callable, cuda_graph) and the runner stores the
boolean; the graph decision is no longer a backend_meta dict. The capture cap
defaults to vLLM's and can be set per run with OPERATORX_CUDA_GRAPH_MAX_TOKENS
(0 = never), since deployments set their own.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
hbarclay and others added 20 commits October 22, 2026 13:15
The importer gives every enroot import private temp/data/runtime paths under
/tmp (B300 homes are node-local). On the H100 DGXC nodes /tmp cannot hold
overlay whiteouts, so the first operatorx import there failed
('failed to create opaque ovlfs whiteout ... Not supported'). A platform entry
can now set enroot_defaults to keep the node's configured paths, as InferenceX's
h100-dgxc launcher imports; cluster:h100-dgxc does.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…r 1..64k tokens

GEMMs come from each checkpoint's weight map (every InferenceX precision variant,
every framework fusion, lm_head and router/mixer gates), 32 token counts from 1 to
65536. fp32-output gates run the matmul vLLM runs for them: torch.mm with an fp32
epilogue, or an fp32 matmul on an fp32 weight. The MoE input buffers now cover 64k tokens.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… qsa, gdn, kda)

One op type per attention module, timed whole from the post-norm hidden states to
the module output. Args are the module's sizes, cache/state dtypes, projection
operands, on/off steps and a (count, q, ctx) request batch; no backend yet.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Each op builds a one- or two-layer model of the checkpoint family that has the
module (real config.json, the op's sizes, a shrunken MLP) with dummy weights; vLLM
allocates the KV cache and picks the attention backend. The batch is scheduled
through vLLM's model runner as requests with ctx tokens already computed (random,
format-valid cache contents), and the timed call is the module forward as the
decoder layer makes it, replayed as a CUDA graph where vLLM would use one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…V4 / V4.1

The cut-down models keep each family's layer arrangement where the KV cache layout or a
module's inputs depend on it: DeepSeek-V4-Pro C4A beside C128A, V4.1's six layer roles
(window, ratio-2 source and consumer, ratio-1 candidate source, consumer and shared
indexer), GLM's indexer layer before its top-k reuser, K3's KDA beside MLA. The timed
module is resolved per op; a reusing layer's capture sees its group's top-k already
converted, as it is in the full graph. vLLM rejecting a config is unsupported.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…3; checkpoint quantization

attn_deepseek_v4 (V4-Pro C4A with fp8 / mxfp4 indexer cache, C128A; V4.1's six layer
roles), attn_kimi_k3 (gated NoPE MLA, KDA with fp32 / bf16 state) and attn_minimax_m3
(dense layers) sweep decode (1-256 requests x 1k-128k ctx), prefill up to 32k tokens,
chunked prefill on 8k-128k ctx and a mixed batch. proj lists the checkpoint's quantized
projections; the backend applies that checkpoint's own quantization_config. The KV
cache is half the device; vLLM rejecting a batch (or a K3 fp8-cache prefill without an
fp8-query prefill backend) is unsupported.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…duler, lazy JIT

The module replay runs in inference mode like the runner's step (in-place ops on the
step's tensors failed outside it). Blocks are allocated for a request whose ctx tokens
are computed, so sliding-window caches keep only the window. vLLM compiles kernels on
first use instead of every shape at startup. vLLM failing to build or warm up a module
config is unsupported.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…er reads it)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ker does

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…'s test

Rank launch and PYTHONPATH use /opx/source/operatorx, the test command runs
operatorx/tests. test_inferencex_generator.py tested scripts/inferencex_testlist,
which this branch removes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… current config

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…endent of linear

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…g, independent of linear"

This reverts commit dbbb2f2: adapting attention to the multi-device work belongs
on that branch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
operatorx/recipes.py finds the recipe InferenceX serves a case's source checkpoint with on
the runner's hardware (expanded by infx.srt_slurm's own selected_recipes); the planner
gives that shard the recipe's image, launch env and server arguments
(OPERATORX_ENGINE_ARGS). The attention engine takes the arguments through vLLM's
EngineArgs parser (the op's own KV and indexer dtypes on top) and the recipe's CUDA-graph
mode and sizes, replacing per-model settings. Replaces the configs/*-master.yaml
recipe lookup that the top-level layout broke. The plan job initializes srt-slurm and
srtctl's dependencies.

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

* operatorx: multi-device gemm, moe and attention under InferenceX recipes

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

* operatorx engine: the recipe's CUDA-graph cap moves into its compilation config

vLLM rejects max_cudagraph_capture_size given both as its own argument and in the
compilation config, which a non-eager engine now receives.

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

* operatorx: smoke_parallel, one case per op family and parallel split

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

* operatorx vllm: images older than the pinned vLLM

Attention sets enable_jit_warmup only where the image's KernelConfig has it; a MoE case
on an image whose vLLM lacks the API the generic block uses is unsupported, not an error
(the DeepSeek-V4 DEP recipe image runs vLLM 0.17).

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

* operatorx engine: expert parallelism stays the recipe's for ops that don't split along it

An attention case on the DeepSeek-V4 DEP recipe (DP attention, MegaMoE experts) kept
the recipe's MoE backend but lost its expert parallelism, which MegaMoE requires.

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

* operatorx attention: DeepSeek-V4-Pro's untimed experts keep the checkpoint's width

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

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…gistry prunes its tag

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
h100-dgxc moved to the AWS dsxe Slurm (as b300): --mem=0, --container-remap-root and
--mpi=none, and the old DGXC enroot-paths workaround goes. Workflow steps source
check_env.sh; CI_zh.md is gone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… / srt-recipe)

InferenceX now names a single-node configuration's model, image and runner in the master
config, whose search space points at the srt-slurm recipe files; recipes no longer carry
model.path / model.container. Lookup walks those entries and expands each referenced
recipe with infx's selected_recipes as before.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@hbarclay hbarclay changed the title operatorx: gemm + moe on NVIDIA and AMD, measured in the serving framework's own layers operatorx: gemm + moe on NVIDIA and AMD Oct 22, 2026
hbarclay and others added 5 commits October 22, 2026 15:39
…pruned

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

A backend's image is the one InferenceX serves that framework with on the runner's
hardware (configs/*-master.yaml); containers.toml is only the fallback where it serves
none. InferenceX pins images as tag@sha256: the planner takes the pinned digest and the
import URI from InferenceX's own enroot_uri (by digest, since enroot 3.x cannot parse
tag@digest). H100 runs on InferenceX's cluster:h100-dsxe runners.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ith its siblings

The AMD overlay replaced CollectiveX's whole operator block, pinning partitions the
clusters no longer have (compute-0); it now adds to it, so the partition and squash
directory are CollectiveX's. ep_harness now imports its sibling ep_oracle: load it with
its directory on sys.path.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ectives.vec

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ceX image

The hardware's default image is InferenceX's too, and can be a nightly tag the registry
has pruned (H100's ddd6fbca): swap it like a pruned recipe image instead of failing the
plan.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@hbarclay
hbarclay merged commit 24e1caa into main Oct 23, 2026
8 checks passed
@hbarclay
hbarclay deleted the hbarclay/operatorx branch October 23, 2026 13:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants