Crown Citadel Research Report

Feasibility Report: Porting ROCmFP4 to Atlas

Technical decision brief on whether Atlas is a worthwhile AMD Strix Halo target for ROCmFP4, based on current engine architecture, weight formats, kernel status, and measured llama.cpp baselines.

Decision Brief

The short version: ROCmFP4 can be reimplemented inside Atlas, but the evidence does not yet justify doing it. The mandatory first step is to prove Atlas is faster than llama.cpp on AMD with standard FP8 weights.

2-4 moEstimated full ROCmFP4 integration effort before optimization risk.
72 / 92Atlas AMD kernels compile in the reported port branch; full serve remains pending.
20 tok/sAtlas AMD README target for Qwen3.6-27B FP8 decode.
28-33 tok/sReported llama.cpp + ROCmFP4 Qwen3.6-27B baseline on Strix Halo.
Recommended gate: run the 1-2 week Atlas-vs-llama.cpp FP8 validation first. Do not start native ROCmFP4 integration unless Atlas FP8 is at least 20% faster on the same hardware and model.

Status: Updated 2025-06-16. Previous version contained incorrect assumptions about ROCm version, automation ceiling, and effort estimates. This version corrects those.

Executive Summary

Verdict: Technically possible, but there is no evidence it will be faster than llama.cpp + ROCmFP4. The effort is high (2-4 months) and the payoff is speculative.

The two projects are architecturally incompatible at the weight format layer:

Dimension ROCmFP4 (llama.cpp fork) Atlas (Rust inference engine)
Weight format GGUF (custom Q4_0_ROCMFP4 tensor type) Safetensors (BF16, FP32, FP8E4M3, UInt8)
Quantization Custom E2M1-derived 4-bit with UE4M3 scales NVFP4 (NVIDIA E2M1 + FP8 scales), FP8 E4M3
Backend ggml (C/C++ with HIP/Vulkan kernels) Custom Rust + CUDA kernels compiled to PTX/HSACO
Model loading GGUF file parser HuggingFace safetensors + config.json
Kernel dispatch ggml op dispatch (generic) Hardware+model+quant auto-discovered kernels
AMD support Native ROCm/HIP + Vulkan WIP port (hipcc shim, 72/92 kernels compile)

The core problem is that Atlas does not support GGUF, Q4_0, or any 4-bit weight format other than NVFP4. To bring ROCmFP4 to Atlas, you would need to add:

  1. 1. A GGUF loader (or a conversion pipeline from GGUF → Atlas's internal format)
  2. 2. A new QuantFormat::RocmFp4 variant
  3. 3. A new WeightDtype for ROCmFP4
  4. 4. Hardware-specific HIP kernels for ROCmFP4 dequantization, matvec, matmul, FlashAttention
  5. 5. Weight loading logic for every model architecture you want to support

The Critical Unknown: Does Atlas Beat llama.cpp on AMD?

This is the question that must be answered before any ROCmFP4 work. The available data suggests it might not.

Baseline: llama.cpp + ROCmFP4 (Already Works)

Model Hardware Format Decode Speed
Qwen3.6 27B Strix Halo gfx1151 ROCmFP4 STRIX_LEAN 33.6 tok/s short, 28.0 tok/s sustained
Qwen3.6 35B A3B Strix Halo gfx1151 ROCmFP4 STRIX_LEAN 104.4 tok/s short, 89.3 tok/s sustained

These are end-to-end, regression-guarded, reproducible numbers. The ROCmFP4 repo has 8 guard scripts that fail CI if these numbers drop.

Atlas on AMD: The Only Data Point

From Atlas's own AMD port README (README-HIP.md):

spark serve Qwen/Qwen3.6-27B-FP8 …; coherence check; decode tok/s via ~/bench-atlas.sh (target 20)

Atlas's own target for Qwen3.6-27B on AMD is 20 tok/s with FP8 weights.

Compare: llama.cpp gets 28-33 tok/s for the same model on the same hardware with ROCmFP4.

So Atlas is targeting to be slower than llama.cpp's current baseline, even before adding ROCmFP4.

Why Atlas's "2-3x Faster" Claim Doesn't Apply Here

Atlas's README says:

We make no compromises or generalizations. Each hardware and model combination has its own unique properties that require fine-tuning custom kernels that leverage the model for that specific hardware configuration. The end result? 2-3x faster kernels all around.

But this claim is only validated on NVIDIA GB10 (Blackwell):

Model Hardware Atlas tok/s Comparison
Qwen3.5-35B-A3B NVFP4 NVIDIA GB10 131 "faster than vLLM on same hardware"
Qwen3.6-35B-A3B FP8 NVIDIA GB10 130 vs vLLM/TensorRT-LLM

There is zero AMD data. Atlas has no published AMD benchmark, no AMD comparison to llama.cpp, no AMD comparison to anything.

Why AMD is Different from NVIDIA

Factor NVIDIA GB10 AMD Strix Halo
Atlas's value prop Model-specific kernels beat generic CUDA Generic ggml already optimized for AMD
Memory bandwidth Tensor cores + HBM3e = compute-bound UMA = bandwidth-bound
Kernel specialization payoff High (tensor core shapes matter) Lower (bandwidth is the bottleneck)
ROCmFP4 tuning N/A (not NVIDIA format) Already done in llama.cpp
Atlas maturity 12+ targets, production 72/92 kernels, serve pending

On NVIDIA, Atlas's model-specific kernels extract value from tensor cores and custom launch geometries. On AMD, the bottleneck is memory bandwidth, and llama.cpp's generic ggml kernels are already very well-tuned for that. The ROCmFP4-specific optimizations (unaligned dword loads, two-warp geometry, Codebook10 expanders) are already in llama.cpp.

The Honest Verdict

Scenario Likelihood Why
Atlas + ROCmFP4 is significantly faster than llama.cpp + ROCmFP4 on AMD Low No evidence; Atlas AMD target is already lower than llama.cpp baseline; AMD is bandwidth-bound where generic kernels already work well
Atlas + ROCmFP4 is roughly equal to llama.cpp + ROCmFP4 Moderate Possible if Atlas's scheduler + Rust runtime offset the format disadvantage
Atlas + ROCmFP4 is slower than llama.cpp + ROCmFP4 Non-trivial Atlas AMD port is incomplete; 20 MMA kernels still need hand-porting; the "target 20" for FP8 is already below llama.cpp's ROCmFP4 numbers

Bottom line: There is no business case for Atlas + ROCmFP4 on AMD based on the available data. The most likely outcome is that you spend 2-3 months and end up with something equal or slower than what already exists.

What You Should Do First: The Minimal Validation Experiment

Before any ROCmFP4 work, answer this question:

Does Atlas's model-specific kernel architecture produce meaningful speedups on AMD with standard weights?

The "Does Atlas Beat llama.cpp on AMD?" Test (1–2 weeks)

Goal: Determine if Atlas's architecture has any speed advantage on AMD at all.

What to do:

  1. 1. Complete the 2–3 MMA kernels needed for Atlas AMD prefill (w4a16_gemm, dense_gemm_tc, inferspark_prefill)
  2. 2. Stub the remaining 17 MMA kernels (they don't affect decode)
  3. 3. Build Atlas AMD
  4. 4. Serve Qwen3.6-27B-FP8 (or Qwen3.6-35B-A3B-FP8) on your Strix Halo
  5. 5. Measure decode tok/s
  6. 6. Run llama.cpp on the same hardware with the same model and FP8 weights
  7. 7. Compare

Decision criteria:

Why this is the right experiment:

Why NOT do the ROCmFP4 integration first:

What is ROCmFP4?

ROCmFP4 is a custom 4-bit quantization format developed for AMD Strix Halo (gfx1151). It is not MXFP4, NVFP4, or a standard Q4_0 variant. It has unique characteristics:

Block Layout


// Dual-scale (Q4_0_ROCMFP4): 18 bytes per 32-weight block, 4.50 BPW
struct block_rocmfp4 {
    uint8_t qs[16];    // 32 packed 4-bit nibbles (E2M1-derived Codebook10)
    uint8_t e[2];      // Two unsigned E4M3 scale bytes, one per 16-weight half
};

// Fast single-scale (Q4_0_ROCMFP4_FAST): 17 bytes per block, 4.25 BPW
struct block_rocmfp4_fast {
    uint8_t qs[16];    // Same 32 packed nibbles
    uint8_t e;         // One UE4M3 scale for the whole block
};

Codebook10 Value Table


static const int8_t rocmfp4_codebook[16] = {
     0,  1,  2,  3,  4,  6,  8, 10,
     0, -1, -2, -3, -4, -6, -8,-10,
};

The value table is not standard E2M1 (which would be {0, 0.5, 1, 1.5, 2, 3, 4, 6}). It is a tuned signed-integer representation where the largest magnitude is retuned from 12 to 10 to reduce outlier pull on Qwen3-family tensors.

Scale Format

ROCmFP4 uses finite unsigned E4M3 scale bytes decoded to half-scale values. This is a custom scale format, not standard FP8 E4M3. The scale decoder builds normal FP32 values directly from exponent/mantissa bits, skipping NaN/Inf handling because ROCmFP4 row validation already rejects non-finite scale bytes.

Tensor-Aware Presets

ROCmFP4 has six presets that mix layouts across tensor roles:

Preset Token Embeds Dense Tensors Attention K/V BPW Use Case
ROCMFP4 Q4_0_ROCMFP4 Q4_0_ROCMFP4 Q4_0_ROCMFP4 4.50 Pure dual-scale
ROCMFP4_LEAN Q5_K Q4_0_ROCMFP4_FAST Q4_0_ROCMFP4 ~4.38 Compact, quality-balanced
ROCMFP4_COHERENT Q6_K Q4_0_ROCMFP4 Q4_0_ROCMFP4 ~4.50 Quality-first
ROCMFP4_FAST Q4_0_ROCMFP4_FAST Q4_0_ROCMFP4_FAST Q4_0_ROCMFP4_FAST 4.25 Speed-only
ROCMFP4_FAST_COHERENT Q6_K Q4_0_ROCMFP4_FAST Q4_0_ROCMFP4_FAST ~4.38 Balanced fast
ROCMFP4_STRIX Q6_K Q4_0_ROCMFP4_FAST Q4_0_ROCMFP4 ~4.49 Strix quality target
ROCMFP4_STRIX_LEAN Q5_K Q4_0_ROCMFP4_FAST Q4_0_ROCMFP4 ~4.38 Strix compact target

This tensor-aware preset system is not something you can simply "drop in" — it requires the inference engine to understand which tensor is which (token embeddings vs. attention K vs. FFN weights) and apply different quantization formats per tensor.

What is Atlas?

Atlas is a pure Rust inference engine with a modular, trait-based architecture. It is fundamentally different from llama.cpp:

Weight Loading Pipeline


safetensors file → parse header → mmap or O_DIRECT read →
  GPU allocation → WeightStore (HashMap<String, WeightTensor>) →
  ModelWeightLoader (per-model) → TransformerLayer objects

Atlas only supports safetensors files. The WeightDtype enum:


pub enum WeightDtype {
    BF16,      // 2 bytes
    FP32,      // 4 bytes
    FP8E4M3,   // 1 byte
    UInt8,     // 1 byte
}

There is no Q4_0, no Q5_K, no Q6_K, no GGUF support. Atlas's architecture assumes weights are in one of these four dtypes, loaded from HuggingFace-style safetensors checkpoints.

Quantization Format Enum


pub enum QuantFormat {
    Nvfp4,  // NVFP4 E2M1 + FP8 block scales
    Fp8,    // FP8 E4M3 block-scaled
}

The forward pass (quant_weights.rs trait) dispatches to model-specific, hardware-specific, quantization-specific kernels. The kernel directory structure:


kernels/
  gb10/
    qwen3.6-35b-a3b/
      nvfp4/          ← NVFP4 kernels for this model on GB10
    qwen3.6-27b/
      nvfp4/
  strix-hip/          ← Would be the AMD target directory
    qwen3.6-27b/
      rocmfp4/        ← Would need to exist

Kernel System

Atlas kernels are CUDA source files (.cu) compiled to PTX for NVIDIA, or compiled via hipcc with compat headers to HSACO (.co) for AMD. The build system (build.rs / build_target.rs) auto-discovers kernels from kernels/<hw>/<model>/<quant>/ directories.

Key kernel types for each (hw, model, quant) target:

For ROCmFP4, you would need to write all of these for the AMD target, using the ROCmFP4 block format and Codebook10 decode in the kernels.

AMD Port Status

The port/amd-strix-halo branch has a partial AMD port:

If the Validation Experiment Passes: Integration Options

Option 1: GGUF-to-Safetensors Converter (2–3 weeks, 1 engineer)

Convert ROCmFP4 GGUF → BF16/FP8 safetensors.

Option 2: Native ROCmFP4 WeightDtype in Atlas (2–3 months, 1–2 engineers)

Add ROCmFP4 as a native packed weight format in Atlas, write decode kernels only.

Option 3: Full Native Integration (3–6 months, 2-3 engineers)

Full ROCmFP4 support: GGUF loader, all kernels, tensor-aware presets, regression guards.

Automation Reality: What an Agent Can Actually Do

The previous version of this report incorrectly stated that ~40% of the work (kernel tuning, regression validation) was "not automatable without hardware." This is wrong. The correct framing is:

The kernel tuning is not a human-vs-agent problem. It is a hardware-access problem. An agent with SSH to a Strix Halo machine can do exactly what the ROCmFP4 author did: hypothesize, code, compile, measure, keep or reject. The autoresearch skill is designed for this.

The Agent's Actual Advantage

A human tuning kernels on Strix Halo would run 5-10 experiments per day (compile + benchmark takes 10-30 min each). An agent running a persistent loop can run 50-100 experiments per day (24/7, no sleep, no bias, perfect record-keeping).

The ROCmFP4 author spent months doing manual tuning. An agent could do it in 1-2 weeks of continuous search because:

  1. 1. It can read the ROCmFP4 README tuning notes as a specification rather than rediscovering them empirically
  2. 2. It can run the compile-measure loop continuously
  3. 3. It never forgets results or gets tired

The Automation Pipeline

Phase A: Specification Automation (1 week, any machine)

Phase B: Converter Automation (1 week, any machine)

Phase C: Kernel Skeleton Automation (2 weeks, any machine)

Phase D: Hardware-Dependent Validation (1-2 weeks, needs Strix Halo)

Total effort with agent: 4-6 weeks for full integration, assuming the validation experiment proves Atlas has value on AMD.

Tools and Dependencies

Tool Purpose Version
ROCm AMD GPU toolchain (hipcc, rocm-smi, rocminfo) 7.2.1 (validated by ROCmFP4-llama CI)
AMD Strix Halo hardware gfx1151 — the only validated target for ROCmFP4 Required for validation
Rust toolchain Atlas is pure Rust Latest stable
CUDA toolkit For reference (NVIDIA target comparison) Optional
ggml source Reference for ROCmFP4 block format and CPU fallback From ROCmFP4-llama repo
safetensors crate Atlas's existing weight format From crates.io
cudarc or hip-rs CUDA/HIP runtime bindings in Rust From crates.io

Note: Atlas's README-HIP.md mentions "ROCm 6.x" but the ROCmFP4-llama repo validates on ROCm 7.2.1. Use whatever version works on your hardware.

Recommendation

Step 1 (Mandatory): Run the minimal validation experiment.

Step 2 (If validation passes): Build the GGUF→safetensors converter (Option 1).

Step 3 (If converter proves valuable): Add native ROCmFP4 decode kernels (Option 2).

Step 4 (Only if deeply justified): Full integration (Option 3).

Critical prerequisite: Atlas's AMD port must be completed first. The current status is 72/92 kernels compile, 20 need hand-porting, full-model serve pending. The validation experiment will also force completion of this prerequisite.

Conclusion

The ROCmFP4 format is a deeply specialized, AMD-tuned, tensor-aware quantization system built on top of llama.cpp's ggml backend. Atlas is a pure Rust, safetensors-based, hardware+model-specific kernel engine with a completely different architecture.

Bringing ROCmFP4 to Atlas is not a "port" in the conventional sense. It is a reimplementation of the ROCmFP4 quantization format, decode kernels, and tensor-aware preset system within Atlas's kernel framework.

But the most important question is not "can we do it?" — it's "should we do it?" And the answer to that depends entirely on whether Atlas's architecture produces speedups on AMD at all. The available data suggests it might not. The only way to know is the 1-2 week validation experiment.

Do not commit to the full ROCmFP4 integration until you have proven that Atlas is faster than llama.cpp on AMD with standard weights.

Report generated by autoresearch skill analysis. Updated 2025-06-16. Sources: github.com/charlie12345/rocmfp4-llama (commit 4860505ee), github.com/Avarok-Cybersecurity/atlas (branch port/amd-strix-halo).