Spaces:
Running
Running
Fix conversion of unnormalized BF16->BF16 weights (llama/7843)
Browse files* add truncate_bf16
* truncate intermediate fp32 if converting bf16 to bf16
* fix masking in __compute_fp32_to_bf16
* np.int16 no longer used
* missing cast and additional numpy 2.x fix
* ggml-impl : do not flush bf16 subnormals to zero
* ggml : add reference fp32 to bf16 conversion
The fast version is no longer equivalent for all platforms
because of the handling of subnormal values.
* gguf-py : remove flush to zero for bf16 subnormals
* gguf-py : remove float32 truncation to bf16
Rounding achieves the same thing in the cases where this was used.
* missed prototype update in merge
* merge cleanup
---------
Co-authored-by: Francis Couture-Harpin <[email protected]>
- ggml/include/ggml.h +1 -0
- ggml/src/ggml-impl.h +3 -6
- ggml/src/ggml.c +9 -2
ggml/include/ggml.h
CHANGED
|
@@ -349,6 +349,7 @@ extern "C" {
|
|
| 349 |
GGML_API ggml_bf16_t ggml_fp32_to_bf16(float);
|
| 350 |
GGML_API float ggml_bf16_to_fp32(ggml_bf16_t); // consider just doing << 16
|
| 351 |
GGML_API void ggml_bf16_to_fp32_row(const ggml_bf16_t *, float *, int64_t);
|
|
|
|
| 352 |
GGML_API void ggml_fp32_to_bf16_row(const float *, ggml_bf16_t *, int64_t);
|
| 353 |
|
| 354 |
struct ggml_object;
|
|
|
|
| 349 |
GGML_API ggml_bf16_t ggml_fp32_to_bf16(float);
|
| 350 |
GGML_API float ggml_bf16_to_fp32(ggml_bf16_t); // consider just doing << 16
|
| 351 |
GGML_API void ggml_bf16_to_fp32_row(const ggml_bf16_t *, float *, int64_t);
|
| 352 |
+
GGML_API void ggml_fp32_to_bf16_row_ref(const float *, ggml_bf16_t *, int64_t);
|
| 353 |
GGML_API void ggml_fp32_to_bf16_row(const float *, ggml_bf16_t *, int64_t);
|
| 354 |
|
| 355 |
struct ggml_object;
|
ggml/src/ggml-impl.h
CHANGED
|
@@ -80,8 +80,9 @@ static inline float ggml_compute_bf16_to_fp32(ggml_bf16_t h) {
|
|
| 80 |
/**
|
| 81 |
* Converts float32 to brain16.
|
| 82 |
*
|
| 83 |
-
* This
|
| 84 |
-
*
|
|
|
|
| 85 |
* This code should vectorize nicely if using modern compilers.
|
| 86 |
*/
|
| 87 |
static inline ggml_bf16_t ggml_compute_fp32_to_bf16(float s) {
|
|
@@ -95,10 +96,6 @@ static inline ggml_bf16_t ggml_compute_fp32_to_bf16(float s) {
|
|
| 95 |
h.bits = (u.i >> 16) | 64; /* force to quiet */
|
| 96 |
return h;
|
| 97 |
}
|
| 98 |
-
if (!(u.i & 0x7f800000)) { /* subnormal */
|
| 99 |
-
h.bits = (u.i & 0x80000000) >> 16; /* flush to zero */
|
| 100 |
-
return h;
|
| 101 |
-
}
|
| 102 |
h.bits = (u.i + (0x7fff + ((u.i >> 16) & 1))) >> 16;
|
| 103 |
return h;
|
| 104 |
}
|
|
|
|
| 80 |
/**
|
| 81 |
* Converts float32 to brain16.
|
| 82 |
*
|
| 83 |
+
* This is binary identical with Google Brain float conversion.
|
| 84 |
+
* Floats shall round to nearest even, and NANs shall be quiet.
|
| 85 |
+
* Subnormals aren't flushed to zero, except perhaps when used.
|
| 86 |
* This code should vectorize nicely if using modern compilers.
|
| 87 |
*/
|
| 88 |
static inline ggml_bf16_t ggml_compute_fp32_to_bf16(float s) {
|
|
|
|
| 96 |
h.bits = (u.i >> 16) | 64; /* force to quiet */
|
| 97 |
return h;
|
| 98 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
h.bits = (u.i + (0x7fff + ((u.i >> 16) & 1))) >> 16;
|
| 100 |
return h;
|
| 101 |
}
|
ggml/src/ggml.c
CHANGED
|
@@ -483,9 +483,16 @@ void ggml_bf16_to_fp32_row(const ggml_bf16_t * x, float * y, int64_t n) {
|
|
| 483 |
}
|
| 484 |
}
|
| 485 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 486 |
void ggml_fp32_to_bf16_row(const float * x, ggml_bf16_t * y, int64_t n) {
|
| 487 |
int i = 0;
|
| 488 |
#if defined(__AVX512BF16__)
|
|
|
|
| 489 |
for (; i + 32 <= n; i += 32) {
|
| 490 |
_mm512_storeu_si512(
|
| 491 |
(__m512i *)(y + i),
|
|
@@ -965,7 +972,7 @@ static const ggml_type_traits_t type_traits[GGML_TYPE_COUNT] = {
|
|
| 965 |
.is_quantized = false,
|
| 966 |
.to_float = (ggml_to_float_t) ggml_bf16_to_fp32_row,
|
| 967 |
.from_float = (ggml_from_float_t) ggml_fp32_to_bf16_row,
|
| 968 |
-
.from_float_ref = (ggml_from_float_t)
|
| 969 |
.vec_dot = (ggml_vec_dot_t) ggml_vec_dot_bf16,
|
| 970 |
.vec_dot_type = GGML_TYPE_BF16,
|
| 971 |
.nrows = 1,
|
|
@@ -20653,7 +20660,7 @@ size_t ggml_quantize_chunk(
|
|
| 20653 |
case GGML_TYPE_BF16:
|
| 20654 |
{
|
| 20655 |
size_t elemsize = sizeof(ggml_bf16_t);
|
| 20656 |
-
|
| 20657 |
result = n * elemsize;
|
| 20658 |
} break;
|
| 20659 |
case GGML_TYPE_F32:
|
|
|
|
| 483 |
}
|
| 484 |
}
|
| 485 |
|
| 486 |
+
void ggml_fp32_to_bf16_row_ref(const float * x, ggml_bf16_t * y, int64_t n) {
|
| 487 |
+
for (int i = 0; i < n; i++) {
|
| 488 |
+
y[i] = ggml_compute_fp32_to_bf16(x[i]);
|
| 489 |
+
}
|
| 490 |
+
}
|
| 491 |
+
|
| 492 |
void ggml_fp32_to_bf16_row(const float * x, ggml_bf16_t * y, int64_t n) {
|
| 493 |
int i = 0;
|
| 494 |
#if defined(__AVX512BF16__)
|
| 495 |
+
// subnormals are flushed to zero on this platform
|
| 496 |
for (; i + 32 <= n; i += 32) {
|
| 497 |
_mm512_storeu_si512(
|
| 498 |
(__m512i *)(y + i),
|
|
|
|
| 972 |
.is_quantized = false,
|
| 973 |
.to_float = (ggml_to_float_t) ggml_bf16_to_fp32_row,
|
| 974 |
.from_float = (ggml_from_float_t) ggml_fp32_to_bf16_row,
|
| 975 |
+
.from_float_ref = (ggml_from_float_t) ggml_fp32_to_bf16_row_ref,
|
| 976 |
.vec_dot = (ggml_vec_dot_t) ggml_vec_dot_bf16,
|
| 977 |
.vec_dot_type = GGML_TYPE_BF16,
|
| 978 |
.nrows = 1,
|
|
|
|
| 20660 |
case GGML_TYPE_BF16:
|
| 20661 |
{
|
| 20662 |
size_t elemsize = sizeof(ggml_bf16_t);
|
| 20663 |
+
ggml_fp32_to_bf16_row_ref(src + start, (ggml_bf16_t *)dst + start, n);
|
| 20664 |
result = n * elemsize;
|
| 20665 |
} break;
|
| 20666 |
case GGML_TYPE_F32:
|