MAX v26.5
Highlights
-
The MAX AI kernels library is now the MAX accelerator library, and most of the GPU programming APIs moved out of the Mojo standard library into a new top-level
maxpackage:std.algorithmtomax.algorithm,std.benchmarktomax.benchmark, andstd.gpu.{compute,host,memory,sync}tomax.gpu.*. The Mojolayoutpackage also now ships with the MAX accelerator library. -
Support for Apple silicon GPUs now extends back to M1 devices. This release also adds hardware-MMA flash-attention prefill for M5 that lowers TTFT by ~1.4x at sequence length 8192. Image generation is also faster on M5: FLUX.2-klein bf16 checkpoints now default to int8 W8A8 quantization for a ~1.45x end-to-end speedup at near-lossless quality, and NVFP4 checkpoints can opt into an int8 requant that runs ~2.56x faster than the default W4A16 path on FLUX.2-dev.
-
Expanded skills for the model bring-up workflow in our skills repo, including
serve-modelto bring up an OpenAI-compatible endpoint withmax serve,benchmark-modelto measure throughput and latency,eval-modelto run accuracy evaluations against a served endpoint, andprofile-modelto profile inference. You can install them in Claude Code from a plugin marketplace with/plugin marketplace add modular/skills, taking either the fullskillsplugin or themax-skillsandmojo-skillssubsets. See AI coding assistants for setup.
Documentation
- Renamed the MAX AI kernels library to the MAX accelerator library, now
including the GPU programming APIs under the new top-level
maxpackage; its API reference moved to/api/mojo/(old links redirect). - Added docstrings across the public APIs of the kernel packages (
linalg,comm,kv_cache,shmem,state_space,pipeline,structured_kernels,profiling_range,builtin_kernels, and thenvmlwrapper), now published in the kernels API reference. - Added instructions for installing Modular's agent skills through the Claude Code plugin marketplace on the AI coding assistants page.
- Brought the OpenAI-compatible REST API reference up to date: each operation
is now its own page under a new
rest-api/index.mdxoverview, and new chat-completion fields and message roles are documented. - Restructured the MAX docs site: removed the
/maxURL prefix and moveddeploy/andinference/underserve/andgraph/underdevelop/. - Moved cloud deployment documentation out of the MAX doc set (redirects added).
MAX models
- Added GLM-5.2 (
GlmMoeDsaForCausalLM) support, extending the GLM-5.1 sparse-attention architecture with cross-layer index sharing.- Added multi-token prediction (MTP) speculative decoding for GLM-5.2
(
UnifiedMTPGlm5_2ForCausalLM), serving the baked-in NextN layer as a single-layer sparse-MLA draft; enabled automatically for GLM checkpoints that ship a NextN layer with--speculative-method mtp. - Added tool-calling, reasoning, and structured-output (
response_format) support to GLM-5.1 / GLM-5.2, enabled with--tool-parser glm45 --reasoning-parser glm45 --enable-structured-output. - Fixed a GLM-5.1-FP8 crash caused by a shared-experts dtype mismatch.
- Added multi-token prediction (MTP) speculative decoding for GLM-5.2
(
- Added Laguna (
LagunaForCausalLM) support forpoolside/Laguna-M.1-NVFP4, including tool calling. - Added DiffusionGemma (
DiffusionGemmaForBlockDiffusion) support forgoogle/diffusiongemma-26B-A4B-it(bfloat16) andnvidia/diffusiongemma-26B-A4B-it-NVFP4; text-only for now. - Added Nemotron-H (
NemotronHForCausalLM) support, NVIDIA's hybrid Mamba-2 + attention decoder, with modelopt per-tensor FP8 and a new Mamba-2 SSD chunked-scan varlen kernel.- Extended Nemotron-H with the Nemotron-3-Nano-30B-A3B hybrid MoE variant and enabled the architecture on Apple silicon GPUs in bfloat16.
- Enabled NVIDIA's official FP8 Nemotron-H checkpoints on Apple silicon (previously crashing or producing all-zero logits) and sped up Nemotron-H decode on Apple M5 by ~41-81%.
- Added support for serving
nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-FP8on Apple silicon via a tiled simdgroup-MMA grouped-FP8 (W8A16) MoE matmul, decoding faster than bf16 at concurrency with half the weight memory.
- Fixed the
max_batch_sizehandling for Nemotron-H. - Added support for the
detailparameter on image and video content parts in chat requests. - Added Ideogram 4 (
Ideogram4Pipeline) support, a text-to-image flow-matching diffusion transformer; serve via/v1/responses.- FP8 checkpoint weights run hot projections on native FP8 GEMMs (~24% faster end-to-end on MI355).
- Added support for
amd/Kimi-K2.7-Code-MXFP4on AMD GPUs. - Expanded Gemma 4 support:
- Added DSpark speculative decoding for Gemma 4 12B
(
UnifiedDSparkGemma4ForCausalLM), DeepSeek's block-drafting method: a small draft transformer drafts a 7-token block per step. Enabled with--draft-model-path deepseek-ai/dspark_gemma4_12b_block7 --speculative-method dflash --num-speculative-tokens 7. - Sped up Gemma4-12B DSpark decode by up to ~1.3x via a packed wide-N shallow-K GEMV, a single-pass streaming argmax kernel, and device graph capture.
- Gemma 4 with MTP speculative decoding (
UnifiedMTPGemma4ForCausalLM) now supports image and video input; previously the vision encoder output never reached the language model, so image prompts were answered as if the model were blind. - MTP speculative decoding now samples recovered tokens from the residual distribution when stochastic acceptance rejects a draft token, preserving the target distribution for argmax draft proposals.
- Added structured-output and tool-calling support via the xgrammar backend, covering Gemma 4's special tool-call format.
- Added float16 support, with the logit softcap and vision pooler run in fp32.
- Added tensor-parallel support for the MoE variant.
- Video inputs now route through the shared
VisionEncoderCache, so a repeated clip is served from cache with no re-encode. - Video decoding now runs on a worker thread, so concurrent requests overlap video decode.
- Improved vision-batch serving latency by concatenating embeddings on-device instead of round-tripping through host numpy.
- Fixed the MoE expert-router softmax being computed in
bfloat16instead offloat32, which degraded MoE quality. - Fixed image/video position and scatter indexing desyncs under chunked prefill, which could corrupt vision embeddings on multimodal prompts split across chunks.
- Fixed crashes in multi-device serving and multi-image batches by making
merge_per_device_buffersrank-agnostic. - Fixed reasoning being dropped after tool results.
- Fixed a vision-batch crash caused by constructing a
Device()instead ofCPU()for host tensors.
- Added DSpark speculative decoding for Gemma 4 12B
(
- Expanded DeepSeek-V3 ModuleV3 support:
- Added NVFP4 (modelopt) weight support, running experts, dense MLPs, and the attention output projection on SM100 block-scaled FP4 matmul kernels.
- Added data-parallel + expert-parallel (DP-EP) and multi-GPU
tensor-parallel + expert-parallel (TP+EP) serving. Note:
Tensor.tono longer implicitly callsF.distributed_broadcast; call it explicitly where needed. - Fixed the FP8 adapter by casting f32 normalization gammas, resolving a dtype mismatch.
- Expanded Kimi K2.5 support:
- Kimi with DFlash speculative decoding
(
UnifiedDflashKimiK25ForCausalLM) now supports image input; previously the vision encoder was not compiled, so image prompts were answered as if the model were blind. - Added support for combining Kimi tool calling with
response_format=json_schemaon the xgrammar constrained-decoding backend.
- Kimi with DFlash speculative decoding
(
- Expanded FLUX.2 support:
- FLUX.2-klein bf16 checkpoints on Apple M5 GPUs now default to int8
W8A8 quantization, ~1.45x faster end-to-end than bf16 on
FLUX.2-klein-4B at near-lossless quality; set
APPLE_FLUX2_INT8_W8A8=0to opt out. - NVFP4 checkpoints can now opt into an int8 W8A8 requant at load on
Apple M5 with
APPLE_FLUX2_INT8_W8A8=1, ~2.56x faster end-to-end than the default W4A16 path on FLUX.2-dev. - Diffusion pipelines now support two denoising-cache backends to skip
redundant transformer passes:
--taylorseer(recommended default, withbalancedandfastpresets) and--first-block-caching; the two are mutually exclusive and both off by default.
- FLUX.2-klein bf16 checkpoints on Apple M5 GPUs now default to int8
W8A8 quantization, ~1.45x faster end-to-end than bf16 on
FLUX.2-klein-4B at near-lossless quality; set
- Expanded Qwen support:
- Added tool-calling and reasoning support to Qwen 3.5 / 3.6.
- Fixed a
Qwen3EmbeddingModelcrash.
- Added per-request LoRA adapter support:
LoRALinearandStackedLinearLoRAextend LoRA to standalone and fused-QKV projections, withLoRAManager.applyswapping target layers in a model. - Improved Eagle3 speculative-decoding performance by removing a redundant concatenate in the draft path.
- Fixed Step-3.5-Flash accuracy and performance.
- Fixed the EAGLE3 MHA draft
lm_headall-gather in pure tensor-parallel mode.
MAX framework
- The graph compiler now fuses query/key RMSNorm followed by rotate-half RoPE
into a single
rms_norm_ropeGPU kernel even when the RMSNorm upcasts tofloat32; numerics match the unfused graph. - Added a
poison-allmode toMODULAR_DEBUG_DEVICE_ALLOCATORthat fills every memory-manager allocation with a configurable NaN-pattern byte (MODULAR_DEVICE_CONTEXT_MEMORY_MANAGER_POISON_PATTERN), so uninitialized device-memory reads trip differential tests without kernel instrumentation. Manual debugging aid, not a default. - Added conda packages
max-benchmark,max-serve, andmax-all, plus amax[all]wheel extra, for parity with the existing wheel extras. - Multimodal pipelines now compile their vision and language models in
parallel via a shared
Modulecontainer andsession.load_all(), cutting compile/load time by up to 1.86x (Qwen3-VL-4B: 614s -> 428s). - Made the compiled-model (MEF) cache key relocatable across install paths: absolute-path-valued pipeline options no longer enter the key, so a cache warmed under one install path hits under another.
- ModuleV3 weights are now sharded and transferred to devices inside the compiled graph rather than via eager ops, reducing per-GPU memory use (about 10 GiB for a DP-EP NVFP4 DeepSeek-V3).
- The VMM defragmenting allocator is now the default memory manager on NVIDIA
GPUs, fixing external-fragmentation OOMs ("plenty free but no contiguous
block"); override with
MODULAR_DEVICE_CONTEXT_MEMORY_MANAGER_VMM=0. Also fixed the earlier opt-in being a silent no-op. - Added a HIP-based VMM defragmenting allocator for AMD GPUs (opt-in via
MODULAR_DEVICE_CONTEXT_MEMORY_MANAGER_VMM=1) on MI300-series hardware. - Coalesced consecutive Metal kernel launches into a single shared command buffer with a tunable op cap, reducing per-launch overhead on Apple GPUs; also restored Metal GPU execution aborted by an unimplemented driver-context stub.
- Improved expert-parallel MoE execution by running the shared expert on a
side stream via
ops.side_stream, overlapping it with the routed-expert computation. - Allowed
float16/bfloat16graphs to loadfloat32checkpoint weights, with the weight adapter casting at load time. - Improved multi-device startup latency by batching replay preface copies into a single submission.
Inference server
- Structured output (constrained decoding) and tool calling:
- Reduced per-iteration latency for structured-output requests: the
grammar bitmask is now unpacked and applied on the GPU in a single
fused kernel (
apply_packed_bitmask), and on speculative-decode models the overlap pipeline enqueues the FSM-advance and bitmask compute in the consuming batch's row order, removing a host synchronization point and a device-side gather across all six speculative-decode architectures. - Fixed a structured-output runaway where a
response_formatschema omitting the root"type"compiled to an unbounded grammar and generated untilmax_length; object-implying schemas are now normalized to"type": "object"before grammar compilation. - Structured-output grammars are now compile-validated at request admission: uncompilable or unsatisfiable schemas return HTTP 400 instead of crashing the model worker, and boolean-valued or non-object root schemas are now accepted per JSON Schema draft-7.
- Structured-output (
response_format) JSON is now emitted compactly, without whitespace around separators, reducing output token count and mitigating runaway generation on Gemma 4. - Kimi tool-call arguments are now grammar-enforced via xgrammar structural tags during constrained decoding.
- Added a pluggable grammar backend for constrained decoding, allowing alternative grammar engines to be selected.
- Fixed intermittently dropped Kimi K2.5 tool calls under
reasoning-enabled
tool_choice="auto": the reasoning parser now also ends a reasoning span at<|tool_calls_section_begin|>when the model omits</think>, so the tool call reaches the tool parser instead of being stranded inreasoning. - Raised the maximum tool function name length from 64 to 1024 characters; longer client-supplied tool names are now accepted instead of rejected with a 400 error.
- Reduced per-iteration latency for structured-output requests: the
grammar bitmask is now unpacked and applied on the GPU in a single
fused kernel (
- Extended the chat completions endpoint: accepts the
rootmessage role (opt-in via tokenizerextra_chat_roles), athinkingcontrol object, dotted tool function names, and per-image and per-request size limits; reconcilesmax_tokenswithmax_completion_tokens; added a schema-awarecoerce_argumentstool-parser hook; and added per-videofps,max_frames, andmax_long_side_pixelsampling hints onvideo_urlcontent parts. - Speculative decoding:
- Speculative decoding now runs to
max_seq_leninstead of early-stopping, allowing requests to reach their full configured length. - Greedy speculative-decode acceptance now uses an exact argmax comparison, improving acceptance correctness for greedy requests.
- Enabled the overlap scheduler for DFlash speculative decoding, reducing per-iteration latency.
- Speculative decoding now runs to
- KV cache and prefix caching:
- Added opt-in SHA-256 KV-cache block hashing: a new
kv_cache_hash_algofield onKVCacheConfig(defaultahash64; opt-insha256andsha256_64), an optional per-requestcache_saltscoping prefix-cache reuse, and support across the host-tier connectors (NullConnector,LocalConnector,TieredConnector) and the dKV external tier (DKVConnector), which advertise accepted algorithms via asupported_hash_algosproperty validated at startup. Default behavior is unchanged. - MAX now refreshes an external KV cache tier's recency when a request's
prefix is served from the on-GPU cache, keeping hot shared prefixes
warm in an external tier such as dKV; set
MODULAR_DKV_DISABLE_G0_TOUCH=1to disable. - Added a Rust-implemented host/disk KV cache connector, selected with
--kv-connector rust_tiered(CUDA-only), with asynchronous onload that overlaps compute. - Sped up host KV-cache allocation for tiered/local KV caching with a fast page-locked allocator (mmap + parallel page-fault + chunked host registration).
- Added a
per_layer_buffersKV cache option backing each layer (including quantized scale buffers) with its own sub-cap buffer, unlocking larger context lengths by relaxing the per-allocation size cap. - Added an
enable_dp_cross_replica_prefix_copyKV cache config flag (default on); disabling it serves cross-replica prefix-cache reuse only from the shared host/disk tier instead of device-to-device copies. - Added int8 KV-cache storage with fp16 block scales (MXint8) for flash attention, halving KV-cache memory footprint at near-parity performance and accuracy with fp16.
- Fixed the KV-cache transfer engine (NIXL, behind disaggregated serving) being NVIDIA-only: packages now ship per-vendor UCX plugin flavors, so KV-cache transfer works on AMD GPUs.
- The dKV connector now supports tensor parallelism (TP > 1) on the multi-tenant path for head-sharded (MHA/GQA), MLA, and GQA head-replicated models, with each GPU handshaking its own per-shard store. Also fixed a cross-shard race where a KV load returning differing block counts could leave a stray in-flight copy that later clobbered a reallocated block.
- The dKV KV-cache connector (
--kv-connector dkv) now supports data-parallel serving and shares its prefix cache across DP replicas, matching thelocalandtieredconnectors. - Data-parallel serving now shares the prefix cache across replicas: GPU
hits are served by device-to-device copy, and the CPU/disk offload
tiers are a single shared pool, so
host_kvcache_swap_space_gbnow sizes one shared host pool for the whole deployment rather than one per replica.
- Added opt-in SHA-256 KV-cache block hashing: a new
- Improved time-to-first-token for multimodal requests: oversized media is now
rejected before its bytes are fully materialized, large
data:base64 decoding runs on a worker thread instead of blocking the event loop, per-video count and byte limits are enforced up front, and multi-MBdata:payloads bypass PydanticAnyUrlparsing via a lightweightDataUrlwrapper. - Made numpy array transport across the API-server-to-model-worker request
queue zero-copy: large arrays (notably vision
pixel_values) ride out-of-band as their own ZMQ frame and are decoded as views, replacing both the copy and shared-memory transports on this path. - Fixed image requests failing with a 400 or 500 across all vision models:
data:URIs with unpadded or URL-safe base64 are now decoded tolerantly, and truncated, animated, or content-negotiated images are validated with a full pixel decode that fails fast as a clean 400. - Changed VLM image (and Gemma 4 video) prefix-cache/routing keys to hash
the raw encoded container bytes plus a resolution
size_tier, making keys stable across torch/BLAS/numpy versions and CPU-vs-GPU. - Added an opt-in
emit_reasoning_contentserver config that emits a reasoning model's chain-of-thought underreasoning_contentinstead ofreasoning; off by default. - Added support for the OpenRouter-style
reasoningrequest field in chat completions. - Chat completions now respect
max_completion_tokensas the preferred way to cap output length, per the OpenAI API spec;max_tokensis still accepted for backwards compatibility. - Added
MAX_SERVE_GRACEFUL_SHUTDOWN_TIMEOUT_S(default 5s) controlling how long the server drains in-flight requests afterSIGTERM, and fixedSIGTERMcutting off in-flight streaming responses immediately — streaming requests are now bounded by the same timeout. - Added request-queue backpressure to MAX serve:
--max-queue-sizerejects new requests with HTTP 429 once the queue to the model worker is full, and--max-pending-requestsstops the worker draining the queue once its prefill queue is that deep. Both default to unbounded; rejections are observable viamaxserve.request_countwithcode="429". - Failed request submissions in the OpenAI-compatible endpoints now surface
as HTTP 4xx/5xx errors instead of a
200 OKstream carrying an error payload; mid-stream errors are still serialized as error events. - Image generation responses on the Open Responses endpoint now report
usage:output_tokens/total_tokenscarry the total pixel count of the generated images andinput_tokensis 0. Previouslyusagewas alwaysnull. - Added an opt-in
MAX_SERVE_STREAM_MIN_CHUNK_TOKENSserver config (default 1 = unchanged) that coalesces streamed SSE output into larger chunks without affecting TTFT; streaming now also truncates output at a stop string, and reasoning and content are emitted as separate chunks so a delta at the boundary no longer carries both fields. - Added HTTP endpoints to fetch and reset expert-parallel load balancing
(EPLB) statistics, plus the
MAX_SERVE_EPLB_PROFILEenvironment variable to enable EPLB stats profiling inmax serve.
Server metrics
- Fixed speculative-decoding metrics being accumulated across all batches since server start; they are now per-batch.
- Added Prometheus counters for structured-output and tool-call failures:
maxserve.tool_call.conformance_errorsandmaxserve.structured_output.grammar_rejections. - Added data-parallel load-balance metrics:
dp_active_token_occupancyanddp_context_token_occupancy. - Added block-level KV-cache metrics:
maxserve.cache.device_blocks_served,maxserve.cache.cross_replica_blocks_copied, andmaxserve.cache.cross_replica_bytes_copied. - Added
MAX_SERVE_OTLP_METRICS_ENDPOINTto push a self-calibrating exponential-histogram shadow (<metric>.exponential) of every histogram metric to an OTLP endpoint, alongside the existing Prometheus/metricshistograms. Unset by default; behavior unchanged. - Added video encoder statistics to the scheduler's per-iteration batch log
(a
Video Encoderclause mirroringVision Encoder) and as OpenTelemetry metrics undermaxserve.video.*. Models managing their own encoder cache implement aSupportsPooledVisionMetricsprotocol so their image and video metrics reach the scheduler. - Fixed the
codelabel on themaxserve_request_countmetric to report the HTTP status actually returned, so requests rejected before generation are counted with their real status code instead of200or dropped. - Added dKV external-tier health metrics: OpenTelemetry gauges
maxserve.dkv.connected_clients,maxserve.dkv.total_clients, andmaxserve.dkv.reconnect_attempts, plus adKV degradedscheduler log clause while any replica client is disconnected. - Added
maxserve.cache.disk_blocks_readandmaxserve.cache.disk_blocks_writtencounters for KV blocks read from and written to the disk cache tier when tiered KV caching is enabled. - Added vision encoder statistics to the scheduler's per-iteration batch log
for multimodal models (images encoded vs. served from the vision encoder
cache, patches and vision tokens), also exported as OpenTelemetry metrics
under the
maxserve.vision.*namespace. - Fixed
maxserve_time_to_first_token_millisecondsunder-reporting TTFT by excluding request parsing and media resolution; expect a step up in reported TTFT that reflects measurement, not a regression. - Fixed inflated
maxserve.cache.h2d_blocks_copiedandmaxserve.cache.d2h_blocks_copiedtelemetry on tiered and local KV cache deployments; counters now report per-batch deltas. - Fixed the input-token metric being double-counted in MAX Serve.
- Fixed max-serve telemetry emitting a batch's token counts alongside the previous batch's timing under overlap scheduling.
- Fixed speculative-decode acceptance metrics leaking from a token-generation batch into a following context-encoding batch.
max CLI
- Improved error messages when a subcommand's components are not installed:
e.g.
max servefrom the base package now names the extra to install (max[serve]) instead of a bareModuleNotFoundError. - Trimmed
max benchmarkdependencies so it no longer requires the full serve dependency set; telemetry is now disabled formax benchmarkandmax list. - Added opt-in token-balanced CE scheduling across data-parallel replicas via
--dp-ce-balance-timeout-ms(default off): new context-encoding requests are priced at their post-prefix-cache length and bound to the least-loaded replica, deferring up to the timeout while per-step occupancy stays under--dp-ce-balance-threshold(default 0.8). Dynamic chunk-size reduction (--dp-ce-balance-enable-dynamic-chunk-size, default on) runs below-threshold steps immediately at a reduced chunk size. - Added
--chunked-prefill-min-chunk-size(default 0 = off) to floor the token size of any chunked-prefill chunk, avoiding degenerate sliver chunks that pay a full step's overhead for almost no progress. - Added an experimental
--fold-sampler-into-graphoption (default off) that folds greedy argmax token selection into the captured forward graph, removing the per-token blocking sampler submission on supported architectures (currently Nemotron-H). Also fixed the serve CLI silently dropping this and related flags on their way to the model worker, which had disabled the folded sampler; with the flags threaded through, decode latency improves substantially. - Added a
max-pending-futuresconfig (default 1, unchanged behavior); setting it to 2 enables experimental schedule-ahead decoding with two forwards in flight per request. - Added
--no-enable-tool-call-constrained-decode(default enabled) to keep--tool-parserparsing of generated text while skipping grammar-based constrained decoding for tool calls. With it disabled,tool_choice=requiredcan no longer force a tool call;--enable-structured-outputis unaffected. - Added a
--top-kMAX Serve flag to set a server-wide default top-k when clients omittop_k; request-supplied values still take precedence. - Added a
max warm-interpreter-cachecommand that batch-compiles the eager interpreter model matrix into the on-disk cache (parallel workers,--jobs,--check,--force) so later programs start warm.max servenow refuses on-demand eager compiles by default (opt back in with--allow-cold-interpreter-cacheorMAX_EAGER_ALLOW_LAZY_COMPILE=1); adopting a warm cache still works. - Fixed KV-cache CLI flags (e.g.
--kv-connector-config) replacing the entirekv_cachesection of a--config-filerecipe instead of overriding just the named setting. - Fixed speculative-decoding CLI flags (e.g.
--num-speculative-tokens) being silently dropped when a--config-filerecipe already set aspeculativesection; flags now merge onto the recipe's values. - Fixed default-valued CLI overrides being silently dropped; explicitly passing a flag equal to its default now overrides recipe/config-file settings.
Python API
- Added
max.graph.ops.reduce_scatter_rms_norm, a distributed op that reduce-scatters a bfloat16 tensor across devices and RMSNorm-normalizes each device's row shard in one collective launch, returning both the normed shard and the residual sum shard; numerically identical to reduce-scatter followed byrms_norm. DeepSeek V3.2 and GLM-5.x now use it in TP-EP non-allreduce mode. - Added
max.graph.ops.allgather_rms_norm, which fuses an all-gather with the following RMSNorm into one kernel launch, returning both the normed tensor and the bit-identical gathered residual. Dispatches to the fused kernel or falls back by shape; not enabled by default in any shipping pipeline. - Added an optional
init_valueargument tomax.graph.ops.buffer_create: the buffer becomes persistent state, allocated and filled once at model load and reused (with mutations preserved) across executions. - Added
max.graph.ops.floor_div(andF.floor_div), element-wise floor division matching Python//. Integer operands stay in the integer domain, so integer floor division compiles on backends without 64-bit float support (for example, Metal GPUs). - Added
max.driver.set_virtual_cpu_target()/get_virtual_cpu_target()to fix the CPU codegen target (for example"x86-64-v3"or"generic") before importingmax._interpreter_ops, so the eager interpreter's CPU kernel cache is host-independent and shippable across hosts of the same architecture family. Mirrorsset_virtual_device_target_arch()for GPUs. - Eager execution in
max.experimentalnow routes every realization through themax.experimental.executor.Executorabstraction, selected byMAX_EAGER_EXECUTOR(defaultcomposite, the same interpreter-then-cached-compile behavior as before). - The eager interpreter now compiles its graph-compiler models lazily, per
target on first dispatch, instead of JIT-compiling the full kernel library
at import; set
MAX_EAGER_OP_PRECOMPILE=1to precompile at import. - The eager interpreter's remaining op families — binary elementwise and
comparison, reduce/softmax/argmax/cumsum, shape-rearrange (
pad,tile,split,concat,slice), gather/scatter, pooling,conv2d,resize,top_k/bottom_k,where,layer_norm/rms_norm,cast,band_part/arg_nonzero/non_maximum_suppression/random/range/roi_align, and the last Mojo-bound ops (transpose,broadcast_to,store_slice) — now run through pre-compiled graph-compiler models instead of hand-written Mojo bindings. No Mojo sources ship, removing the multi-minute first-import JIT compile. Structural parameters stay runtime operands, so one compiled graph per(op, device, dtype)serves every shape. - Small eager-interpreter behavior fixes from the migration:
band_partgained CPU float64 on Apple silicon;arg_nonzerono longer caps input rank;rangeraises on a non-evenly-divisible interval or zerostep;random.uniformsamples may differ between eager and compiled graphs from the same seed. - Added
max.graph.Dim.substitute, which replaces named symbols in a dimension with other dims or static values, folding the result through the compiler's own attribute evaluation. Unmapped symbols are left intact, and a static dimension is always returned unchanged. - Added
max.graph.KernelLibrary.has_shape_function, reporting whether a kernel in a loaded library registered a shape function. - Added
max.experimental.nn.subgraphableforModulesubgraph compilation: a repeated block lowers to one shared subgraph reused per call (share across modules by passing aname), cutting graph size and compile time — the DeepSeek-V3 ModuleV3 MoE decoder block now compiles as one reused subgraph. Opt out withModule.compile(..., allow_subgraphs=False). max.nn.hooks.PrintHooknow supportsmax.experimental.nn.Module.- Added
F.print, supporting both single-device and multi-device tensors. - Added
max.graph.default_custom_extensions()and thedefault_custom_extensions_scope()context manager: registered paths are merged into thecustom_extensionsof every newGraph, so a backend's custom-op library is reachable without an explicitcustom_extensions=. - Added
PipelineArgs(max.pipelines) as the user-facing input type for constructing pipelines, consolidating construction arguments into a single explicit type instead of scattered flat kwargs. - Added
max.experimental.compile_pool.ProcessCompilePool, which compiles graphs in parallel background worker processes; eager execution now compiles out of process, so a first eager call on a warm MEF cache drops from ~5.6s to ~16.7ms. - Added
InferenceSession.compile_async, which schedules compilation on the runtime worker pool and returns a pendingCompiledModel;InferenceSession.compilenow wraps it and blocks. - Added
max.engine.readfor loading a compiled-model artifact (.mef) without anInferenceSession; the result can be initialized on any session viaInferenceSession.init. - Added a LoRA wrapper to
max.experimental.nn.common_layers: wrap aLinearorQKVLinearin place to add a ragged multi-adapter delta fed as per-call graph inputs (GPU-only, Mojo SGMV); the QKV path uses a single fused LoRA-B expand op, simplifying weight loading and theStackedLinearLoRA/LoRAMixininterfaces. - Added a
tile_based_fusionoption (defaultFalse) tocompile/loadin the graph API, enabling tile-based codegen at the graph-API level. - Added a
fused_qk_rms_norm_rope_raggedPython wrapper, exposing the fused QK RMSNorm + RoPE ragged paged kernel to graph building. - Added a
model_nameproperty tomax.driver.Device. - Made several previously private modules public so their APIs are officially
documented: the
GGUFWeightsloader wrappers inmax.graph.weightsand themax.profiler.cpu/max.profiler.gpumodules. - Added
max.experimental.testingwith a sharedassert_all_closehelper for eagermax.experimental.Tensortests. - Added a
PipelineModel.sampler_custom_extensionshook so custom extensions are threaded into the token-sampler graph.
C API
- Fixed
M_borrowTensorInto()copying instead of borrowing a GPU input: device pointers already on the target accelerator are now borrowed in place (zero-copy) on CUDA, so in-place mutation of aBufferTypemodel input is visible to the caller. Host pointers are still staged via copy, as are device pointers on AMD and Apple.
GPU programming
Most GPU programming APIs formerly packaged with Mojo have been rehomed into the
MAX accelerator library, including most of the std.gpu package (now
max.gpu), TileTensor, and LayoutTensor. Some low-level APIs remain in the
standard library.
Device context and execution
-
DeviceGraphBuilder.add_function()now covers every liveDeviceContext.enqueue_function()form, so any kernel launchable on a device context can also be recorded as a graph node:-
Added an overload that takes the kernel as a compile-time parameter and compiles it automatically, so callers no longer need a separate
DeviceContext.compile_function()step:def build(mut builder: DeviceGraphBuilder) raises {read}: _ = builder.add_function[kernel]( 42, grid_dim=1, block_dim=1, dependencies=[] ) -
Added overloads accepting a
DeviceExternalFunctionloaded from PTX/SASS viaDeviceContext.load_function(), and a capturing kernel as a compile-time parameter with runtime arguments. -
All
add_function()overloads now accept alocationargument so wrappers can attribute launch errors to their callers, and the closure overload now accepts (and honors) afunc_attributeargument.
-
-
DeviceGraphBuilder.collect_dependencies()now accepts an optionaldependenciesargument. The named predecessor handles become ambient predecessors of every node theworkclosure adds, so the scope's nodes run after those predecessors without the closure threading the handles through to eachadd_*call. With the default (empty)dependenciesthe behavior is unchanged. Whenworkadds no nodes, the returned join node falls back to depending ondependenciesso it still chains correctly.var producers = builder.collect_dependencies(add_producers) # Every node added by `add_consumers` depends on `producers`: var consumers = builder.collect_dependencies( add_consumers, dependencies=[producers] ) -
DeviceContext.load_function()now keys its runtime cache on the requested entry-point name as well as the blob. Loading two different entry points (for example,kernel_aandkernel_b) from a single PTX/cubin blob no longer collides—previously the second load silently returned the function resolved by the first. The cache also no longer keys on the entire blob when no module name is supplied: it keys on a short hash of the blob instead, so each call avoids copying, hashing, and byte-comparing the whole blob (and retaining a duplicate of it). The win scales with blob size and matters most for large multi-entry blobs loaded on the per-execution path. -
The
DeviceStreamtype is now included in the API reference documentation. Returned byDeviceContext.create_stream()andDeviceContext.create_external_stream(), it provides methods for synchronizing and sequencing asynchronous GPU work (for example,synchronize(),record_event(), andenqueue_wait_for()). The type was already public but was previously hidden from the generated docs.
Kernel arguments and address spaces
-
IntandUIntno longer conform toDevicePassableand can no longer be passed as arguments to GPU kernels (viaDeviceContext.enqueue_function()orcompile_function()). They are platform-sized index types whose bit width depends on the host, so passing them to an accelerator miscompiles when the host and device disagree on the width (for example, a 64-bit host driving a 32-bit GPU index domain). Use a fixed-width type—Int32,Int64,UInt32, orUInt64—for kernel scalar arguments and parameters, and convert back withInt(...)inside the kernel body if you need a platformIntthere. A kernel that still takes a bareInt/UIntargument now fails to compile with: "Int and UInt are not passable to device kernels; use a fixed-width type such as Int32 or Int64 instead". -
The GPU device-side standard library now uses the unified safe
Pointertype throughoutstd.gpu(memory,compute,intrinsics,sync, andprimitives). Public signatures that previously took or returnedUnsafePointerare respelled to barePointer; sincePointerandUnsafePointershare representation and origin and decay implicitly, this is a type-identical change for callers. One visible difference:external_memory()now returns a safePointerinstead of anUnsafePointer. Code that performs raw pointer arithmetic on the result can use theunsafe_offset()method. -
AddressSpaceis now target-extensible rather than a fixed, portable enum. The built-in GPU spaces (GENERIC,GLOBAL,SHARED,CONSTANT,LOCAL,SHARED_CLUSTER,BUFFER_RESOURCE) are unchanged, but accessing any other name—for example, an accelerator-specificAddressSpace.SCRATCHPAD—now resolves through the active hardware backend instead of being a hard-coded compile error. The set of valid address-space names is the union of the built-in GPU spaces and whatever the active backend defines, so accelerator backends can provide their own named spaces (with their own values) only where they exist. A name that no backend defines remains a compile-time error. -
Coordnow conforms toDevicePassable, so aCoordembedded in aDevicePassabletype (such as aTileTensor'sLayout) is encoded to the device throughCoord._to_device_type()instead of a raw field bit-copy, the same wayIndexListalready was. -
coordis now a comptime expression, andcoord[DType]()has been renamed todyn_coord[DType](). You can now writevar my_coord = coord[1, 2, 3]to create aCoord[ComptimeInt[1], ComptimeInt[2], ComptimeInt[3]].
Warp and matrix primitives
-
Atomic.compare_exchange()now accepts aweakparameter, and requiresweak=Trueto compile on Apple GPU targets: AIR exposes no strong compare-exchange primitive, so Metal only lowers theweakform. This is safe for the common case of a CAS-retry loop, since a spurious failure just costs one extra iteration. Previously any use ofcompare_exchange(), including helpers built on it like atomic scatter-reduce, failed to compile on Metal. -
Added
warp.match_any()andwarp.match_all():match_any()returns, for each warp lane, the mask of lanes whose value has the same bits, andmatch_all()returns the warp's active-lane mask if every lane holds the same bits and 0 otherwise. They use NVIDIA'smatch.any.syncandmatch.all.syncinstructions, areadfirstlaneballot fold on AMD, and a shuffle-based emulation on Apple Silicon GPUs. -
warp.vote()now works on Apple Silicon GPUs. Metal's AIR backend exposes no usable ballot intrinsic, so it emulates the ballot with an XOR-butterfly OR-reduction oversimd_shuffle_xor, returning a 32-bit mask (or aDType.uint64mask whose upper 32 bits are always zero); NVIDIA and AMD are unchanged. -
Added an 8x8
simdgroup_matrixmatrix multiply-accumulate primitive (_mma_apple_8x8()) withapple_mma_load_8x8()/apple_mma_store_8x8()fragment helpers for Apple Silicon GPUs instd.gpu.compute.arch. Unlike the 16x16 path (Apple M5 only), the 8x8 primitive is available on all Apple GPU generations (M1-M5). It acceptsFloat16,BFloat16, andFloat32inputs with aFloat32accumulator. -
Apple M5
simdgroup_matrixMMA now accepts FP8 (float8_e4m3fn,float8_e5m2) inputs with an F32 accumulator, alongside the existing F16/BF16/F32 and 8-bit integer types.
Device targeting and hardware support
-
GPUInfo.vendorhas been removed. It duplicatedGPUInfo.api, which identifies the vendor precisely ("cuda","hip","metal", or a stdlib plugin's own API name) rather than collapsing every plugin accelerator into one enum value. Compareapiinstead:comptime use_apple_path = ctx.default_device_info.api == "metal"Vendoritself remains, as the classifier behindhas_amd_gpu_accelerator(),has_nvidia_gpu_accelerator(), andhas_apple_gpu_accelerator(). -
A bare
--target-acceleratorarchitecture (for example,gfx950orsm_90) is now handled identically to its vendor-prefixed form (amdgpu:gfx950,nvidia:sm_90). Previouslyhas_amd_gpu_accelerator(),has_nvidia_gpu_accelerator(), andhas_apple_gpu_accelerator()only recognized the vendor-prefixed spelling, so code that specialized on them (such as warp-tiling parameters) could silently take the wrong path and fail a downstreamcomptimeconstraint.amd:<arch>is also now accepted as an alias foramdgpu:<arch>, mirroring the existingnvidia:<arch>prefix. -
The GPU
Vendortype can now be imported fromstd.sys(from std.sys import Vendor). It remains importable fromstd.gpu.host.infofor backward compatibility. -
Added support for the Steam Deck's RDNA2 Van Gogh APU.
Removed
-
Removed the deprecated
DeviceContext.compile_function_experimental()andDeviceContext.enqueue_function_experimental()methods, along with overloads that passed the kernel twice. UseDeviceContext.compile_function[func]()andDeviceContext.enqueue_function[func]()instead. -
Removed the
UInt-returning GPU indexing accessors (thread_idx_uint,block_idx_uint,block_dim_uint,grid_dim_uint,global_idx_uint,lane_id_uint,warp_id_uint). Use theInt-returningthread_idx,block_idx,block_dim,grid_dim,global_idx,lane_id, andwarp_idaccessors instead. -
Removed the
store_volatile()andload_volatile()intrinsics fromstd.gpu.intrinsics. UsePointer.unsafe_store[volatile=True]()andPointer.unsafe_load[volatile=True]()instead, which work across all supported GPU targets rather than NVIDIA only. -
Removed the deprecated
GPUAddressSpacealias forAddressSpace. UseAddressSpacedirectly.
MAX kernels
- GPU sampling and token selection:
- Sped up GPU token sampling with
top_k >= 10by 2-4x by fusing softmax, temperature scaling, and min-p masking into the rejection-sampling kernel. - Improved the GPU top-k kernel: it now streams past the previous N=2048
cap, with a new single-pass block-wide bitonic sort
(
persistent_topk_block). - Made the top-k + top-p sampler's RNG offset batch-invariant, so sampling results no longer depend on batch composition.
- Fixed GPU sampling kernel bugs: unwritten output when a per-row
top_kis 0, division-by-zero inapply_gumbel_noise_kernelattemperature=0, and NaN-handling bugs in thetopkkernel.
- Sped up GPU token sampling with
- Sped up GPU softmax with a new split-K path for few-row, wide-column shapes, significantly improving BF16 1024x4096 and 256x4096 cases on both B200 and MI355X.
- Fixed the streaming GPU argmax failing to launch for reductions over more than 65,535 rows.
- Attention
OrMaskandChunkedMaskpatterns are now handled natively by the mask iterator, avoiding slower generic fallback paths. - Added float16 MMA support on NVIDIA GPUs, enabling float16 matmuls on NVIDIA tensor cores.
- Improved tiny-M small-N FP32 GEMM performance by routing those shapes to a split-K GEMV kernel.
- Sped up matmul by checking out-of-bounds only on border tiles.
- Added fast RMSNorm GPU kernels: a single-pass kernel for small static-shaped rows and a barrier-free warp-per-row kernel.
- Fixed mis-aligned memory accesses in the
rms_normreduction kernels and inlayer_norm_cpu's sum reduction. - Added
fused_qk_rms_norm_rope_ragged_pagedandfused_dual_qk_rms_norm_rope_raggedGPU kernels fusing QK RMSNorm with rotary embeddings over ragged paged inputs; the dual variant also enables scale-free FP8 KV caches. - Sped up the Gated DeltaNet recurrence kernel by tiling one CTA per value head.
- Added an initial functional MegaFFN kernel.
- Fixed an expert-parallel decode crash when
estimated_total_mfloored to zero. - Added support for non-unit dilation in the CPU direct convolution kernel.
- SM100 (Blackwell) attention and sparse-attention kernels:
- Fixed rare crashes in the SM100 attention kernels: an
illegal-instruction fault in flash-attention prefill under chunked
prefill with tensor parallelism,
cta_group=2TMEM teardown faults, and an out-of-bounds shared-memory write in the 1Q split-K combine kernel. - Fixed a hang in the SM100 FA4 attention kernel on all-masked rows
(
valid_length=0). - Improved the SM100 FA4 flash-attention kernel: softmax warp-path optimizations and support for cluster sizes 6, 8, 10, and 16 across more multi-GPU configurations.
- B200 decode attention partitioning is no longer restricted to powers of 2, improving decode performance for more batch and head configurations.
- Improved the SM100 MLA prefill kernel: added a 1Q (
num_qo=1) mode, Programmatic Dependent Launch for the generic BF16 path (up to ~1.37x on short sequences), and support forv_head_dim != qk_nope_head_dim. - Added native FP8 sparse MLA decode and prefill kernels for SM100, and
extended prefill head-count coverage with a 64-head path and
num_heads=8support. - Added an SM100 tensor-core FP8 MLA sparse-indexer scorer kernel and improved sparse MLA prefill indexer performance via tensor-core scoring over query tiles.
- Sped up the SM100 MLA sparse decode kernels by ~29% on the bf16 path and ~8% on the fp8 path.
- Fixed sparse-attention kernel bugs: a crash during CUDA-graph capture in the sparse MLA decode dispatch, wrong results from the sparse MLA indexer with prefix-cached values, a top-k shared-memory overflow, and an MLA indexer fill bug.
- Fixed rare crashes in the SM100 attention kernels: an
illegal-instruction fault in flash-attention prefill under chunked
prefill with tensor parallelism,
- Added Layout-E and Layout-g MMA paths for MHA prefill, improving attention performance on supported NVIDIA GPUs.
- Enabled the Mojo SM100 FP32 GEMM in the kernel dispatcher, with optional
1D bias and an
allow_tf32opt-out to force full-FP32 precision. - Added weight prefetching to the SM100 block-scaled and structured matmul kernels.
- B200 collective communication:
- Enabled the low-latency (Lamport) all-reduce on B200 for small messages (up to 1 MiB at 2, 4, and 8 GPUs), roughly 1.1-1.68x faster than the one-stage path.
- Added a fused Lamport all-reduce + RMSNorm kernel with PDL early launch, with column-aware dispatch on 8-GPU B200 (up to ~1.14x on the decode-critical-path collective).
- Added a fused GEMM+ReduceScatter kernel that overlaps computation with communication on B200 (~10% faster than unfused for prefill shapes).
- Sped up B200 MoE grouped matmul by removing a per-step synchronization.
- Retuned the SM100 MoE decode kernels from 4-12 to 6 pipeline stages: ~5-7% better decode latency for MXFP8 grouped matmul and up to ~11% throughput for the NVFP4 down-projection at higher active-expert counts, with no change to numerics.
- Fused SM100 projection and GEMM kernels:
- Added a fused GEMM+Bias+SwiGLU kernel for SM100 (B200), exposed to
graphs as
mo.matmul_swiglu(~1.06-1.12x faster than unfused). - Added
expand_qkv_sm100, a single-launch fused LoRA-B QKV expand kernel for SM100. - Added a fused MXFP8 QKV matmul kernel with paged KV-cache write.
- Added a fused QKV + indexer-QKV projection matmul kernel for sparse-attention MLA models (~1.5-2x faster than the unfused pair).
- Added a fused GEMM+Bias+SwiGLU kernel for SM100 (B200), exposed to
graphs as
- Fixed FP8 MHA silently underflowing P values to 0.0 by scaling them before the softmax accumulation.
- Fixed the SFB
n_groupper-lane computation and an N-edge out-of-bounds access insmall_bn. - Fixed MXFP8 block-scaled matmul dispatch misses by falling back to cuBLAS on unsupported shapes.
- Fixed
LAUNCH_OUT_OF_RESOURCESfailures during graph capture on SM100 by declaring the launch block size on the block-scaled small-BN matmul kernel. - Fixed an unaligned-access bug in the NVFP4 quantization async kernel.
- Fixed the
cluster_mask_basecomputation for tall clusters. - Fixed GEMM kernels producing incorrect or out-of-bounds C stores for partial tiles and odd sizes (multistage GEMM, SM100 small-MN GEMM).
- Fixed the vendor-BLAS matmul ignoring the layout row stride, which could compute wrong results for strided inputs.
- AMD GPU kernels:
- Sped up GPU RMS norm on AMD CDNA4 (MI355X) by roughly 15-31% on prefill-sized shapes.
- Extended the AMD MHA prefill kernel with depth-80 support and partial (non-power-of-two) head dimensions.
- Fixed an AMD MHA decode crash caused by too many split-K partitions.
- Added speculative-decode query-token folding to the AMD MHA decode kernel for higher multi-token decode throughput.
- Reworked the AMD sparse-attention decode path: rewrote the
sparse-indexer decode scoring and top-k as faster split-K partition
kernels (fixing a
max_num_blocksdouble-count), and added multi-token (MTP/speculative) support across the gfx950 FP8 MLA decode and sparse-indexer top-k kernels. - Fused MXFP4 expert-parallel operations on AMD MI355X (activation + quantize into down-projection, scale preshuffle into producer/dispatch kernels): +37% total TPM and -15% mean TPOT on an MXFP4 MoE model.
- Improved AMD MXFP4 matmul and grouped-matmul performance via weight preshuffling, register staging, double buffering, async loads, and shared-memory swizzling.
- Optimized all-gather and reduce-scatter on AMD CDNA4 (MI355X), bringing 4-GPU bf16 collectives to the PCIe fabric roofline (all-gather ~2.7x its previous default).
- Sped up expert-parallel dispatch and combine on AMD GPUs via a volatile-load spin loop and reduced atomic contention.
- Sped up float32 matmul/GEMV on AMD GPUs: enabled the GPU matmul kernel
for
float32(fixing graph capture), dispatchedfloat32GEMV to vectorized/split-K paths (52us to 4us in decode), and enabled split-K for skinny-deep shapes (up to ~10x on small shapes). - Sped up bfloat16 matmul on AMD RDNA 3+ GPUs with faster WMMA-based kernels.
- Fixed a race in the AMD 4-wave split-K matmul kernel.
- Fixed the GEMV launch grid writing past the end of the output tensor on AMD GPUs.
- Routed the AMD float32 MoE router through the cached GEMV path.
- Apple GPU kernels:
- Extended Apple silicon GPU support for MAX models to M1 and M2 systems by fixing the optimized matrix multiplication kernels on those GPUs.
- Made the split-K decode attention kernel the default for
token-generation attention on Apple GPUs (paged-KV-cache MHA and GQA
decode);
MODULAR_ENABLE_APPLE_NAIVE_FA_DECODE=0opts out. - Restored the 32-bit atomic
scatter_ndreduce path on Apple GPUs. - Further optimized the Apple M5 GEMM kernels; neural-accelerator utilization rose from 85% to 95%, within 2-3% of MPS.
- Added Apple M5 int8 W8A8 matmul optimizations for NT layouts.
- Added a hardware-MMA flash-attention prefill kernel for Apple M5 (Metal 4) with paged-KV support, giving ~1.4x lower TTFT at seq=8192 (bf16, head dim 128).
- Added a fused online-im2col bf16 conv2d kernel for Apple M5 (Metal 4) and sped up its gather/MMA path by ~4x.
Breaking changes
- Dynamic CE chunk sizing in the data-parallel load-balancer
(
--dp-ce-balance-enable-dynamic-chunk-size) now defaults to off; re-enable it explicitly where its TTFT win holds for your workload. - Removed the deprecated
--max-num-stepsCLI flag andmax_num_stepsconfig field; the pipeline always runs single-step decode and passing the flag now errors. - Replaced
PipelineTokenizer.eos(scalar) withPipelineTokenizer.eos_token_ids(a set of the declared EOS plus any terminators from the model config'seos_token_identries). - MAX Serve now fails at startup when the device KV cache cannot hold a
single request at the configured max sequence length (previously a warning
followed by a runtime crash); the error reports the largest
--max-lengththat fits. max.nn.Module.build_subgraph()now takes representative input values (inputs=) instead of input types (input_types=); update call sites frombuild_subgraph(name, input_types=[v.type for v in values])tobuild_subgraph(name, inputs=values).DistributedTransformerBlocknow acceptslist[PagedCacheValues]directly.- Removed the
MAX_SERVE_METRIC_LEVELandMAX_SERVE_DETAILED_METRIC_BUFFER_FACTORenvironment variables; MAX Serve now always emits its full metric set. To record no metrics (previouslyMAX_SERVE_METRIC_LEVEL=NONE), setMAX_SERVE_METRIC_RECORDING_METHOD=NOOPorMAX_SERVE_DISABLE_TELEMETRY=1. - Removed
InferenceSession.use_old_top_k_kernel()and theUSE_OLD_TOP_K_KERNELenvironment variable; the two-stage top-k kernel is now used unconditionally. - The
Input,Output,MutableInput,FusedInput, andFusedOutputIOSpecvalues are now static members ofIOSpecinstead of module-level aliases; qualify them asIOSpec.Inputetc. (e.g.Tensor[IOSpec.Input, spec]). - Removed the
compilerMojo package; import the 4 re-exported symbols fromextensibilitydirectly. - Renamed the metric
maxserve_cache_hit_rate_percent_utilization(OTELmaxserve.cache.hit_rate) tomaxserve_cache_request_prefix_coverage_percent(OTELmaxserve.cache.request_prefix_coverage); derive a token-weighted hit rate frommaxserve_cache_hits_tokensandmaxserve_cache_misses_tokens. - Removed the EXAONE model architectures (
exaoneandexaone_modulev3); EXAONE checkpoints are no longer served. - Removed
InferenceSession.read; usemax.engine.readto load a compiled-model artifact (.mef) without a session, then initialize it on any session viaInferenceSession.init. - Removed the
MAX_USE_EAGER_INTERPRETERenvironment variable; eager execution is now selected byMAX_EAGER_EXECUTOR(usecompileto force compilation), andEagerRealizationContext(use_interpreter=...)is deprecated in favor ofexecutor=.... - Removed eager-interpreter support that only existed through broken or
GPU-only Mojo bindings:
conv2d_transpose(cuDNN-dependent, crashed on Apple GPUs),resize_bicubic, and CPUgroup_norm(now raisesNotImplementedError; GPU still works). - Narrowed the eager interpreter's CPU coverage to float32/float64 for most float families (the previous Mojo bindings also accepted float16/bfloat16); unsupported dtypes now raise immediately.
- Changed
TileTensorto drop itselement_sizeparameter; element width is now carried byStorage=PointerStorage[element_width=N], or useTileTensor.vectorize(). - Moved accelerator-programming APIs from the Mojo standard library into the
maxpackage:std.algorithm->max.algorithm,std.benchmark->max.benchmark, andstd.gpu.{compute,host,memory,sync}->max.gpu.*. - The
layoutpackage is now bundled with MAX instead of Mojo. - Renamed
LayoutTensor.get_immutable()toas_imm(); the old name remains as a@deprecatedalias. - Deprecated the Python
localandtieredKV cache connectors in favor of the Rustrust_tieredconnector (--kv-connector rust_tiered, CUDA-only); the Python connectors remain for backward compatibility. - Made the
max.entrypointspackage private (max._entrypoints) and deprecatedmax.entrypoints.LLM; a new offline-inference API will follow in a future release. - Renamed the FLUX.2 int8 W8A8 override env var
FLUX2_KLEIN_INT8_W8A8toAPPLE_FLUX2_INT8_W8A8; the old name is still honored with a one-time deprecation warning. - The dKV connector now requires a non-empty tenant identity
(
MODULAR_DKV_TENANT_ID); the empty-tenant default path is removed, so every deployment routes through the per-tenant region-sharded store. A single-tenant multi-GPU node must set the dKV server's--fair-share-partitionsto its GPU count. - Made the tiered (disk) KV cache offload ephemeral: the disk tier starts
empty and removes its
max_kv_tiered_*directory on shutdown; use dKV for persistent KV across runs. - Retuned the Prometheus/OpenTelemetry histogram buckets for MAX
metrics: boundaries are now generated instead of hand-written, matched
to each histogram's actual range (latencies to 8 hours, token counts to
100M) with a leading
0boundary. Dashboards and alerts that hardcodelevalues need updating. - Changed
maxserve.cache.num_used_blocksandmaxserve.cache.num_total_blocksfrom counters to gauges; the exported series drops the counter_totalsuffix.
Fixes
- Fixed Apple GPU issues:
- Fixed a per-kernel-launch memory leak on macOS Metal that accumulated autoreleased driver objects for the lifetime of the thread.
- Fixed three Apple Metal kernel bugs (
rope_ragged,concat,split) that silently produced zeros on Metal. - Fixed the FlashInfer top-k/top-p samplers returning out-of-top-K tokens on Apple GPUs.
- Fixed models failing on pre-M5 Apple silicon GPUs (NVFP4 weights, MHA, and 2-D convolution fallbacks).
- Fixed GPU programming issues:
- Targeting an MI250X now works. While normalizing the architecture name,
gfx90awas rewritten to the nonexistentgfx90aa, so both--target-acceleratorandGPUInfo.from_name()reported every spelling of the target (gfx90a,mi250x,amdgpu:gfx90a, andamd:gfx90a) as an unsupported architecture. - Fixed
print()anddebug_assert()emitting garbled output on AMD GPUs when a printed string's byte length was an exact multiple of 8. The AMDGPUhostcallprintf interface reads each string up to its nul terminator, and the terminator was being dropped in that case, so the host read past the payload. - #6784,
#6434 -
math.sqrt()onFloat64now works on NVIDIA GPUs. NVIDIA has no approximate F64sqrt, so it lowers to the IEEE correctly-rounded hardwaresqrt(sqrt.rn.f64) instead of being rejected at compile time. TheFloat32fast path continues to usesqrt.approx.ftz.f32.
- Targeting an MI250X now works. While normalizing the architecture name,
- Fixed
--model-revisionand--model-overridewith an external weights repository or path being resolved against the base model repo, failing weight downloads. - Fixed a custom op with a data-dependent output dimension killing the process when its kernel registers no shape function; it now reports a compile error.
- Fixed MAX Serve containers ignoring
SIGTERMduring model cold start, leaving pods stuckTerminatinguntil the grace period elapsed; the image now runs underdumb-init, so pods shut down promptly and release their GPUs. - Fixed
max servecrashing on startup withTypeError: cli_serve() missing 1 required positional argument: 'task'. - Fixed
max servefailing at startup with adevice_graph_captureerror for models in the overlap-scheduler auto-disable list (e.g. Gemma 4) when--device-graph-captureis passed explicitly. - Fixed a hang during
max serveshutdown after failures (e.g. OOM). - Fixed
max warm-cachecrashing in virtual-device (compile-only) mode with--draft-model-path. - Fixed a graph-compilation failure on B200 for models with materialized attention masks, such as the padded text encoders in diffusion pipelines (e.g. FLUX.2's Qwen3 text encoder).
- Fixed structured-output, tool-calling, and reasoning issues:
- Fixed the structured-output grammar backend silently defaulting to
llguidanceinstead ofxgrammarfor models launched viamax serve. - Fixed structured-output responses being truncated when the model
sampled an extra
eos_token_idmid-response. - Fixed an explicitly empty (
{}) or boolean-trueJSON schema inresponse_formatbeing treated as "no structured output" instead of "any valid JSON value". - Fixed
response_formatconstraints being dropped after an auto tool call for Gemma 4 and Kimi K2.5. - Fixed Gemma 4 tool-call structured output enforcing JSON Schema
minLength/maxLengthas a token count rather than a character count. - Fixed grammar enforcement being intermittently dropped during speculative decoding: across tool-call structural tags, mid-span when a committed draft span contained a terminating token, and batch-wide when a single request was preempted.
- Fixed a grammar FSM off-by-one at the chunked-prefill-to-decode seam that could misalign constrained-decoding state.
- Fixed streaming tool-call glitches: dangling tool calls with empty arguments, structural namespace tokens leaking into assistant content (MiniMax M2), empty SSE packets while the parser consumed structural tokens, and same-index tool-call entries split across a chunk.
- Fixed the tool-call conformance check turning successful responses
into 500 errors or dropping valid tool calls when a client schema
failed validation; parameter-less tools are no longer flagged as
unknown_tool. - Fixed non-streaming chat completions leaking a literal
<tool_call>marker intomessage.contentwhenmax_tokenstruncated mid tool-call block; the response now surfaces only the preceding content withfinish_reason == "length". - Fixed Kimi tool-call arguments decoding unconstrained under
tool_choice="auto"when the model opened a tool call without a closing</think>, and the combined tools +response_format=json_schemagrammar letting non-conforming output through. - Fixed Gemma 4 with MTP speculative decoding crashing the model worker on the first tool-call grammar.
- Fixed non-streaming Kimi reasoning responses returning null
message.contentwhen the model stopped without</think>, and added validation rejecting out-of-range or non-finitefrequency_penalty/presence_penaltyvalues. - Fixed replayed assistant
reasoningbeing silently dropped when sent back to chat completions;reasoning_contentis also accepted. - Fixed Nemotron-3-Nano leaking chain-of-thought and a raw
</think>delimiter intomessage.contentand emitting zero tool calls withtool_choice="required"; it now defaults--reasoning-parserand--tool-parsertoqwen3_5.
- Fixed the structured-output grammar backend silently defaulting to
- Fixed
ops.scatter_add/scatter_mul/scatter_max/scatter_minand theirscatter_nd_*variants silently dropping concurrent updates whenindicescontains duplicates; reductions are now atomic on CPU and GPU. - Fixed
scatter/scatter_addwriting out of bounds under multi-device sharding inmax.experimental, corrupting unrelated allocations. - Fixed the compiled-model cache (
.max_cache) serving stale compiled models after Mojo kernel-library changes; kernel edits now correctly trigger recompilation. - Fixed sparse-attention (MLA) issues:
- Fixed sparse-attention MLA models (DeepSeek V3.2, GLM 5.1/5.2) with an FP8 latent KV cache falling back to a dense prefill path that cost accuracy and long-context performance.
- Fixed the SM100 sparse MLA prefill kernel reading the wrong layer's KV cache for every layer above the first, silently corrupting attention for multi-layer sparse-attention models (DeepSeek V3.2, GLM 5.1/5.2); also enabled the kernel for GLM 5.2 tensor-parallel head shards.
- Fixed sparse MLA top-k dropping the indexer
-1pad sentinels, which could corrupt padding handling in sparse-attention index selection. - Fixed a warp-collective deadlock in the sparse MLA decode indexer kernel.
- Fixed disaggregated
prefill_onlyserving of DeepSeek V3.2 ignoring the sparse indexer's top-k selection.
- Fixed speculative-decoding issues:
- Fixed speculative decoding (Eagle) requests stopping short of the
per-request
max_tokenscap, returningfinish_reason="length"with fewer tokens than requested. - Fixed the first structured-output request on a speculative-decode (EAGLE) server stalling ~7-9 seconds with the GPU idle.
- Fixed a crash taking down the decode-only engine on disaggregated (1p1d) deployments running structured output with Eagle3 speculative decoding.
- Fixed Eagle speculative decoding with FP4-quantized models: Kimi K2.5
with MXFP4 weights produced garbage tokens, and pairing an FP4 target
with a
bfloat16Eagle3 draft failed to load. - Fixed DeepSeek-V3.1-NVFP4 multi-token prediction failing to load with expert parallelism enabled.
- Fixed the float32 weight-path fallback firing for any model, breaking architectures without f32 support (e.g. f32-only Eagle3 drafts).
- Fixed speculative decoding (Eagle) requests stopping short of the
per-request
- Fixed precision loss in
rms_norm,layer_norm,group_norm(and fused variants) where a smallepsilonsuch as1e-6was silently rounded inbfloat16;epsilonis now carried asfloat32. - Fixed MAX crashing the model worker on the first host KV-cache
offload/reload with
--kv-connector dkv. - Fixed memory-planning and OOM issues:
- Fixed over-provisioned KV-cache offload budgets
(
host_kvcache_swap_space_gb,disk_offload_max_gb) OOM-killing the server or filling the disk mid-startup; thelocalandtieredconnectors now fail fast with an actionable error. - Fixed the VMM defragmenting allocator failing large contiguous allocations, which could OOM long-context KV caches despite free memory.
- Fixed steady device-memory drain during serving; model inputs now reuse fixed-capacity backing buffers.
- Fixed memory planning failing on devices that report zero free memory.
- Fixed a
ValueErrorduring memory planning for diffusion pipelines. - Fixed the Gemma 4 vision encoder running one unbounded forward pass over every image regardless of chunked prefill, which could OOM the model worker on many-image requests.
- Fixed multimodal serving OOMing under load despite free device memory; the vision encoder cache no longer fragments the allocator and releases over-limit entries promptly.
- Fixed Gemma 4 activation-memory estimation under-estimating with tensor parallelism (TP=2) plus MTP speculative decoding, causing OOMs.
- Fixed over-provisioned KV-cache offload budgets
(
- Fixed a use-after-free of pinned buffers when multiple streams were in use in the driver.
- Fixed a token-input staging buffer race under the overlap scheduler that could corrupt inputs.
- Fixed multimodal serving issues:
- Fixed a crash in vision encoder cache assembly on a prefix-cache hit covering an evicted image.
- Fixed Kimi-K2.5 device graph capture failing with an input-count mismatch after the vision cache migration.
- Fixed two crashes in disaggregated serving of vision-capable models.
- Fixed tensor-parallel and expert-parallel accuracy and performance issues in DeepSeek-V3 ModuleV3, and added device-graph-capture support.
- Fixed a GPU memory fault in
grouped_matmul_raggedfor unquantized bf16 MoE experts under expert parallelism on SM100 (e.g. GLM 5.2 NVFP4's MTP draft). - Fixed a crash on data-parallel replicas with no assigned requests.
- Fixed a FLUX.2 multi-GPU accuracy regression.
- Fixed failures loading models whose
transformersAutoConfig is not registered in the installedtransformersversion. - Fixed Hugging Face weight and dataset downloads failing with
FileNotFoundErroron a racy.incompletecache entry; downloads now retry past the transient race. - Fixed grouped (
groups > 1)ops.conv2d/ops.conv3don CPU raisinggrouped conv requires packed filterfor non-constant filters. - Fixed
max.nn.WeightNormConvTranspose1draisingAttributeErrorwhen constructed with the defaulthas_bias=False. - Fixed
max.experimental.nn.Conv2d.forwardfailing with a device mismatch when the bias started on a different device than the input. - Fixed
max.experimental.functional.while_loopraisingAttributeErrorat graph-construction time. - Fixed slicing and
view()on amax.driver.DevicePinnedBuffersilently returning a plainBuffer, causing unexpected device synchronization onto_numpy(). - Fixed
max.driver.set_virtual_device_*()settings having no effect on macOS device creation. - Fixed
DeviceContext.load_functionreturning the wrong function when loading two entry points from one PTX/cubin blob. - Fixed
top_k/bottom_kmis-shaping or rejecting graphs using a negativeaxis. - Fixed
sliding_windowbeing silently dropped when combined with a causal mask. - Fixed AMD GPU issues:
- Fixed an AMD MLA decode crash for models with
num_heads > 16on short prefills of 2-8 tokens, common with multi-turn prefix caching. - Disabled the v2 attention prefill kernel on AMD GPUs due to a race producing NaNs.
- Fixed NaNs from the fused SwiGLU kernel on AMD GPUs.
- Fixed a correctness race in the AMD expert-parallel combine kernel.
- Fixed diffusion models failing on AMD RDNA GPUs.
- Fixed an AMD MLA decode crash for models with
- Fixed
usagereporting at zero-token edge cases:prompt_tokens=0in the final streaming chunk and nullusagein non-streaming completions. - Fixed image/video URL fetches being rejected by some hosts (now sends a
browser
User-Agent) and failing with a 500 on slow or large transfers (now a clean 4xxInputErroron timeout). - Fixed requests containing unpaired UTF-16 surrogates (e.g. a truncated emoji) crashing the tokenizer; they are now replaced with U+FFFD.
- Fixed the benchmark harness crashing with a 500 when flushing the prefix
cache on diffusion models;
/reset_prefix_cachenow returns a clean 400 for pipelines without a KV cache. - Blocked the MagicYUV video codec pending a fix for CVE-2026-8461; video input using that codec is now rejected.
Mojo language
For all the updates to the Mojo language, standard library, and tools, see the Mojo release notes.