xai-org/x-algorithm · error · NotImplementedError

Only f16 and bf16 are supported, got dtype: {dtype}

Error message

Only f16 and bf16 are supported, got dtype: {dtype}

What it means

The FA3-style kernel only implements f16 and bf16 paths — fp32, fp8, or integer dtypes are rejected with NotImplementedError since the tensor-core wgmma instructions assumed by the kernel need half precision.

Source

Thrown at phoenix/xrex/pallas/ranker_attention_fa3.py:108

        raise ValueError(f"q, k, and v should all be 4D, got: {q.ndim=}, {k.ndim=}, {v.ndim=}")
    batch_size, q_seq_len, num_q_heads, head_dim = q.shape
    _, kv_seq_len, num_kv_heads, _ = k.shape
    kv_shape = (batch_size, kv_seq_len, num_kv_heads, head_dim)
    if k.shape != kv_shape:
        raise ValueError(f"Expected {k.shape=} to be {kv_shape} (inferred from q)")
    if v.shape != kv_shape:
        raise ValueError(f"Expected {v.shape=} to be {kv_shape} (inferred from q)")
    if (dtype := q.dtype) != k.dtype or dtype != v.dtype:
        raise ValueError(
            f"q, k, and v should all have the same dtype, got: {q.dtype}, {k.dtype}, {v.dtype}"
        )
    if num_q_heads % num_kv_heads:
        raise ValueError(f"{num_q_heads=} must be divisible by and {num_kv_heads=}")
    q_heads_per_kv_head = num_q_heads // num_kv_heads
    if head_dim % 64:
        raise ValueError(f"{head_dim=} must be divisible by 64")
    if jnp.dtype(dtype) not in map(jnp.dtype, [jnp.float16, jnp.bfloat16]):
        raise NotImplementedError(f"Only f16 and bf16 are supported, got dtype: {dtype}")

    max_concurrent_steps = min(config.max_concurrent_steps, kv_seq_len // config.block_kv)
    block_q, block_kv = config.block_q, config.block_kv
    if kv_seq_len % block_kv:
        raise ValueError(f"{kv_seq_len=} must be a multiple of {block_kv=}")

    def kernel(q_ref, k_ref, v_ref, bound_ref, out_ref, lse_ref, scoped):
        batch = lax.axis_index("batch")
        q_head = lax.axis_index("heads")
        q_seq = lax.axis_index("q_seq")
        smem_buffers, buffer_barriers, consumed_barriers, schedule_barrier = scoped
        wg_idx = lax.axis_index("wg")
        qo_smem2, k_smem, v_smem, lse_smem2 = smem_buffers
        k_barriers, v_barriers, q_barriers = buffer_barriers
        k_consumed_barriers, v_consumed_barriers = consumed_barriers
        history_lower_bound = plgpu.load(bound_ref, (batch, 0))
        history_upper_bound = plgpu.load(bound_ref, (batch, 1))
        candidate_lower_bound = plgpu.load(bound_ref, (batch, 2))

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Cast inputs: q.astype(jnp.bfloat16) (and same for k, v)
  2. For numeric debugging use attention_reference instead of the pallas kernel

Example fix

# before
q, k, v = jnp.ones(...), ...  # float32
# after
q, k, v = (x.astype(jnp.bfloat16) for x in (q, k, v))
Defensive patterns

Strategy: validation

Validate before calling

assert q.dtype in (jnp.float16, jnp.bfloat16), "cast inputs to fp16/bf16"
q, k, v = (x.astype(jnp.bfloat16) for x in (q, k, v))

Prevention

When it happens

Trigger: Passing q/k/v in jnp.float32 (the JAX default for randn), float8, or any dtype outside {float16, bfloat16}.

Common situations: Forgetting to cast synthetic test inputs; enabling fp32 debugging; new user passing default-dtype arrays without a params initialization.

Related errors


AI-assisted analysis of xai-org/x-algorithm@24c60942c5 (2026-08-28). Data as JSON: /api/errors/57c541a6d4674f52. Report an issue: GitHub.