From 8647bda84ab5d40570588c4a39845a32a0849ee4 Mon Sep 17 00:00:00 2001 From: kkkzbh <145212963+kkkzbh@users.noreply.github.com> Date: Sat, 13 Jun 2026 19:30:33 +0800 Subject: [PATCH 1/2] fix(cpu): preserve raw fp16 bits in x86 quantize --- .../kernels/common/ggml/quantize/quantize.hpp | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/mllm/backends/cpu/kernels/common/ggml/quantize/quantize.hpp b/mllm/backends/cpu/kernels/common/ggml/quantize/quantize.hpp index e318451a1..ba315dba0 100644 --- a/mllm/backends/cpu/kernels/common/ggml/quantize/quantize.hpp +++ b/mllm/backends/cpu/kernels/common/ggml/quantize/quantize.hpp @@ -30,6 +30,7 @@ #include #include #include +#include #include "mllm/core/DataTypes.hpp" @@ -105,8 +106,26 @@ inline static float lookup_fp16_to_fp32(uint16_t f) { #else namespace mllm::cpu { -#define MLLM_COMPUTE_FP16_TO_FP32(x) _cvtsh_ss(x) -#define MLLM_COMPUTE_FP32_TO_FP16(x) _cvtss_sh(x, 0) +template +inline static uint16_t mllm_fp16_bits(const T& f) { + if constexpr (std::is_integral_v>) { + return static_cast(f); + } else { + static_assert(sizeof(T) == sizeof(uint16_t), "fp16 type must be 16 bits"); + uint16_t s; + memcpy(&s, &f, sizeof(s)); + return s; + } +} + +inline static mllm_fp16_t mllm_fp16_from_bits(uint16_t bits) { + mllm_fp16_t f; + memcpy(&f, &bits, sizeof(bits)); + return f; +} + +#define MLLM_COMPUTE_FP16_TO_FP32(x) _cvtsh_ss(mllm_fp16_bits(x)) +#define MLLM_COMPUTE_FP32_TO_FP16(x) mllm_fp16_from_bits(_cvtss_sh(x, 0)) static float table_f32_f16[1 << 16]; static bool table_f32_f16_init = false; @@ -127,7 +146,7 @@ inline static float lookup_fp16_to_fp32(uint16_t f) { } #ifndef MLLM_FP16_TO_FP32 -#define MLLM_FP16_TO_FP32(x) lookup_fp16_to_fp32(x) +#define MLLM_FP16_TO_FP32(x) lookup_fp16_to_fp32(mllm_fp16_bits(x)) #endif #ifndef MLLM_FP32_TO_FP16 #define MLLM_FP32_TO_FP16(x) MLLM_COMPUTE_FP32_TO_FP16(x) From 7011227bef4c38dbdd121c5e94863f5a7c0e34fc Mon Sep 17 00:00:00 2001 From: kkkzbh <145212963+kkkzbh@users.noreply.github.com> Date: Sat, 13 Jun 2026 19:52:04 +0800 Subject: [PATCH 2/2] docs(cpu): explain x86 fp16 bit helpers --- mllm/backends/cpu/kernels/common/ggml/quantize/quantize.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mllm/backends/cpu/kernels/common/ggml/quantize/quantize.hpp b/mllm/backends/cpu/kernels/common/ggml/quantize/quantize.hpp index ba315dba0..48e9540ec 100644 --- a/mllm/backends/cpu/kernels/common/ggml/quantize/quantize.hpp +++ b/mllm/backends/cpu/kernels/common/ggml/quantize/quantize.hpp @@ -106,6 +106,8 @@ inline static float lookup_fp16_to_fp32(uint16_t f) { #else namespace mllm::cpu { +// Extract a raw 16-bit fp16 bit pattern without numeric conversion. Integral inputs +// are already bit patterns; non-integral fp16-like values are copied byte-for-byte. template inline static uint16_t mllm_fp16_bits(const T& f) { if constexpr (std::is_integral_v>) { @@ -118,6 +120,7 @@ inline static uint16_t mllm_fp16_bits(const T& f) { } } +// Construct an mllm_fp16_t value from a raw 16-bit fp16 bit pattern. inline static mllm_fp16_t mllm_fp16_from_bits(uint16_t bits) { mllm_fp16_t f; memcpy(&f, &bits, sizeof(bits));