Comfy 量化格式¶
Comfy 量化检查点是标准的 safetensors 文件,包含量化权重、缩放张量和逐模块配置。一个检查点可以混合多种量化格式和普通浮点层。ComfyUI 在支持的情况下会选择原生内核,并在某个格式的快速路径被禁用时,将权重反量化后以计算 dtype 执行。
检查点布局¶
保留模型正常的 state-dict 名称。每个量化模块都会新增一个 <module>.comfy_quant 张量,该张量以一维 uint8 数组的形式包含 UTF-8 JSON。例如,一个 FP8 线性层包含:
blocks.0.proj.weight # quantized weight
blocks.0.proj.weight_scale # weight scale
blocks.0.proj.bias # ordinary floating-point bias, if present
blocks.0.proj.comfy_quant # encoded {"format": "float8_e4m3fn"}
要在现有 state dict 中编码配置:
import json
import torch
config = {"format": "float8_e4m3fn", "full_precision_matrix_mult": True}
state_dict["blocks.0.proj.comfy_quant"] = torch.tensor(
list(json.dumps(config).encode("utf-8")), dtype=torch.uint8
)
format 是必需的。没有 comfy_quant 的模块会正常加载。逻辑权重维度来自模型的模块定义;计算 dtype 在运行时选择。不需要文件级别的层映射或 format_version 字段。较旧的 _quantization_metadata safetensors 头和 scaled_fp8 检查点会在加载时转换;新文件应使用逐模块条目。
权重格式¶
下面的所有张量名称都带有相同的 <module>. 前缀。N 是输出宽度(或词汇表大小),K 是输入宽度,G 是量化组大小。除非另有指定,缩放张量为 FP32。
format |
weight 存储 |
缩放张量 |
|---|---|---|
float8_e4m3fn |
FP8 E4M3FN, [N, K] |
weight_scale:标量 |
float8_e5m2 |
FP8 E5M2, [N, K] |
weight_scale:标量 |
nvfp4 |
FP4 E2M1 打包为 uint8,填充前为 [N, K/2] |
weight_scale:FP8 E4M3FN 块缩放,每组 16 个;weight_scale_2:全局标量 |
mxfp8 |
FP8 E4M3FN,填充前为 [N, K] |
weight_scale:E8M0 二的幂次块缩放,每组 32 个 |
int8_tensorwise |
int8, [N, K] |
weight_scale:标量或每行 [N, 1] |
convrot_w4a4 |
有符号 INT4 打包为 int8, [N, K/2] |
weight_scale:每行 [N] |
asym_w4a8_int8 |
4 位编码打包为 int8, [N, K/2] |
weight_s_rel:FP8 E4M3FN 或 FP32 [N, K/G];weight_s_channel:FP32 [N] |
w6a8_int8 |
均匀 6 位编码打包为 int8, [N, 3K/4] |
weight_s_rel 和 weight_s_channel,同上 |
NVFP4 和 MXFP8 使用 Comfy Kitchen 的分块/交织(blocked/swizzled)缩放布局,权重维度分别填充为 16 和 32 的倍数。它们的块缩放以及 FP8 weight_s_rel 也可以作为原始 uint8 字节存储。使用该布局的量化器和 QuantizedTensor.state_dict(prefix) 来生成正确的打包、填充和缩放键;再单独添加 comfy_quant。
格式选项¶
选项位于模块的 comfy_quant JSON 中:
| 选项 | 适用范围 | 行为 |
|---|---|---|
full_precision_matrix_mult |
线性层和 MoE 权重 | 默认 false。设为 true 时保留量化存储,但在计算 dtype 下反量化后用于矩阵乘法;它不会强制 FP32。 |
convrot |
int8_tensorwise |
默认 false。启用分组 Hadamard 旋转;导出带每行缩放的旋转后权重。 |
convrot_groupsize |
旋转 INT8 和所有打包整型格式 | 旋转组大小,默认 256。打包整型格式始终使用旋转。 |
linear_dtype |
convrot_w4a4 |
"int4"(默认)或 "int8" 选择乘法路径;存储的权重保持 INT4。内部 quant_group_size 固定为 64。 |
group_size |
asym_w4a8_int8, w6a8_int8 |
权重缩放组大小,默认 16。 |
num_experts |
MoE 专家库 | 保存时写入的专家数量;加载时模型定义提供维度。 |
线性层/MoE 加载器也接受嵌套 params 对象中的旋转、组大小和 linear_dtype 选项;顶层值优先。嵌入层的旋转选项必须位于顶层。
asym_w4a8_int8 可选存储 weight_codebook,一个浮点 [16] 查找表;没有它时,编码使用均匀电平。w6a8_int8 没有码本。导出这些格式时需使用对称权重:ComfyUI 加载器不会使用 Comfy Kitchen 的可选 weight_correction 张量。
旋转组必须能整除 K,并且是 4 的幂。W4A4 还要求 K 能被 64 整除。对于分组的 W4A8,K 必须能被 16 和 G 整除;G 必须至少为 4,并且要么能整除 16,要么是 16 的倍数。W6A8 要求 K 能被 32 整除,并且 G 是 16 的倍数。加速后端可能会施加进一步的形状限制。
激活与平滑¶
- FP8: 可选的
input_scale提供校准后的标量激活缩放。没有它时,缩放为1.0。 - NVFP4: 可选的
input_scale提供全局激活缩放;否则根据当前输入计算。块缩放是动态的。 - MXFP8: 激活块缩放是动态计算的;量化器不会使用存储的
input_scale。 - 整型格式: 接受浮点输入,并在所选内核内部对激活进行量化。它们不加载
input_scale。 - NVFP4 平滑: 可选的
pre_quant_scale在线性运算之前乘以输入。导出权重时需进行相应的反向调整。
校准是为了选择有代表性的固定激活缩放,而不是为了使用具有动态激活缩放的格式。偏置保持浮点。
嵌入层与 MoE¶
量化嵌入层支持 float8_e4m3fn、float8_e5m2 和 int8_tensorwise,包括 INT8 每行缩放和可选旋转。查找时会对选中的行进行反量化;省略时嵌入层缩放默认为 1.0。
使用 MoEExperts 的模型可以将专家库存储在同一个模块前缀下。权重和每个专家的缩放系数带有前置的专家维度 E;可选偏置为 [E, N]。标量缩放系数可以共享。带有逐行缩放系数的分组 W4A8/W6A8 和 INT8 库也可以存储,并将专家/输出行展平为 E * N。MoE 库不会加载 input_scale 或 pre_quant_scale。
线性权重使用 ComfyUI 正常的卸载(offloading)和 LoRA 修补(patching)路径。模块 state-dict 保存会写入量化张量、缩放系数以及受支持的配置。
注意力偏好¶
带有 ComfyAttention 子模块的注意力模块可以使用相同的 uint8 JSON 编码来存储 <module>.comfy_attention.config。这与权重量化无关。提供一个对象或有序列表:
ComfyUI 在加载过程中会为主设备选择第一个受支持的偏好。未知方法会被跳过并产生警告;不可用的方法会被跳过。空列表或没有可用偏好时,正常的注意力选择机制保持生效。显式注意力覆盖优先。保存时保留完整的偏好列表,包括不支持的条目。
仅接受上述两种方法。SOL 公开了 tau(默认 1.0);值越高,通过精确注意力的块越少。其他 SOL 选项使用 Comfy Kitchen 默认值。SOL 要求 FP16/BF16 Q/K/V 输入相匹配,且头维度为 128。带掩码的调用使用 PyTorch 注意力;low_precision_attention=False 不会禁用 SOL。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 co/ComfyUI