Skip to content

Owned CUDA embedding has no memory-reducing storage dtype — an 8B embedder needs ~16GB where int4 serving needs ~5-6GB #9

Description

@iceteaSA

Verified at 1675e6d. Filed as a capability gap with a concrete blocked deployment, not as a defect — the current behaviour looks deliberate, but its consequence is a hard exclusion on shared GPUs and I could not find it stated anywhere.

What the code does

StorageDType in crates/synapse-engine-cuda/src/lib.rs has exactly one variant:

pub enum StorageDType {
    F16,
}

from_str accepts only "f16"/"fp16" and returns UnsupportedDType for anything else. The safetensors loader accepts f32/f16/bf16 inputs (model.rs:187, :218) but resolves serving storage to f16. There are zero Rust references to quantized, q8_0, or Q8_0 anywhere in the crate.

The Q8_0 kernels are present but are not a memory path

Worth stating precisely, because their presence suggests an easier fix than exists. port/cuda_family_common.cuh defines dequantize_q8_0 and a quantized flag, and copy_matrix uses them — but that path:

target.quantized = source.q8_0 != nullptr;
target.fp32.allocate(elements);          // full-width allocation regardless
if (target.quantized) {
    target.q8_0.allocate(bytes);         // plus the quantized buffer
    ...
    dequantize_q8_0<<<...>>>(target.q8_0.pointer, target.fp32.pointer, elements);
}

It allocates the full fp32 matrix and the q8 buffer, then dequantizes device-side. So it is a host→device transport compression, not resident-VRAM reduction — the quantized case ends up using more device memory, not less. Whatever the right fix is here, "wire up the Q8 kernels that already exist" is not it, and I would rather say so than file an issue that implies a two-line change.

The blocked deployment

Evaluating whether synapse could serve an existing embedding workload on a homelab box:

  • Corpora (Hindsight + OpenClaw) are indexed at 4096-dim on Qwen3-Embedding-8B. Interop with those indexes requires that exact model — a smaller embedder forces a full re-index and a retrieval-quality drop, which that team already refused once for a 768-dim swap.
  • Today it is served int4 at roughly 5-6GB by a custom FastAPI container with a VRAM admission gate, on an RTX 5090 (32GB, CC 12.0) shared with a reranker, a llama.cpp server, ASR, and TTS. The admission gate bounds the shared set to about 15GB.
  • Under synapse the same weights are f16: 8B x 2 bytes is roughly 16GB, before activations.

So it is excluded by the admission budget, and the hardware is not the reason — CC 12.0 clears the device_meets_floor bar of 7.5 comfortably. It clears the compute floor and loses on memory.

Numbers marked as estimates: the 16GB figure is arithmetic from the dtype, not a measured load. A live nvidia-smi measurement of the int4 baseline and real headroom is being taken on that box and I will post it here when it lands, including if it contradicts this.

What I am not asking for

Not asking for int4 specifically, and not proposing a design — the dtype surface is yours and picking a quantization scheme is a decision about accuracy the engine owner makes, not the consumer. Nor is this a request to change the ONNX or Metal paths.

The narrow ask is whether f16-only is an intentional permanent constraint for owned CUDA embedding. If it is, that is a legitimate answer and worth one line in the docs, because the consequence — models above roughly 7B are unservable on a shared 32GB card, and above ~15B on a dedicated one — is currently only discoverable by reading lib.rs. Related to #8, which is the same discoverability problem on the crate list.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions