mirror of
				https://github.com/ggml-org/llama.cpp.git
				synced 2025-10-30 08:42:00 +00:00 
			
		
		
		
	ggml-cpu: enable IBM NNPA Vector Intrinsics (#14317)
* ggml-cpu: add nnpa compile flag Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> (cherry picked from commit4a9f60c201) * ggml-cpu: add fp16->fp32 nnpa first Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> (cherry picked from commit8d4a7987f9) * ggml-cpu: add fp32->fp16 Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> (cherry picked from commit0ff0d65162) * ggml-cpu: better variable names Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> (cherry picked from commit2f58bbcbb8) * docs: update s390x docs Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> (cherry picked from commit01b929491b) * ggml-cpu: add debugging prints to see if dlf16 is correct Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: fix print vs printf Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: fix float placeholder Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: ensure fp16 and fp32 load and stores are called Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: fp16 load ensured to hit Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: remove sigint from fp16 store for some reason, the function is not getting a hit when debugged with gdb. we will need to investigate further Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: activate nnpa for ggml_cpu_fp16_to_fp32 Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: nnpa activate ggml_cpu_fp16_to_fp32 for 8 elements Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: nnpa switch to vec_xst test Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: switch to vec_xst for 4 element loops also Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: rework noop Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: remove noop, general code cleanup Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: clarify variable naming Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: activate nnpa for ggml_cpu_fp32_to_fp16 Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: add breakpoint for debugging Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: test fix for conversion failure Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: disable fp32->fp16 nnpa conversions for now there are some conversion failures in nnpa that requires the eyes of an ibm stsm. will create a separate pr to introduce the fp32->fp16 change. Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: switch to elif macro Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: reattempt fp32->fp16 Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: fix typo Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: reattempt fp32->fp16 Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: fix compiler types Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: change to typedef vector types Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: add 4 element loops for fp32->fp16 Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: clarified vector naming Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: bring back fp32->fp16 store nnpa Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: activate nnpa fp32->fp16 or fp16->fp32 compute Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: add nnpa macro check in ggml-impl Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: add missing __func__ Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: diagnose why __NNPA__ macro is not being defined Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: import vecintrin.h to fix compiler errors Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: update macro tests Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: move s390x typedef to own header file Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * Revert "ggml-cpu: move s390x typedef to own header file" This reverts commit157f856c34. Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: switch to importing ggml-cpu-impl instead Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: fix macro declaration Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: test more macros Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: add debug prints Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: bruteforce macro definitions Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: move macro definitions Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: add ggml-impl.h to cmakelists Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: switch to private macros Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: move s390x typedef to own header file Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> (cherry picked from commit157f856c34) * ggml-cpu: move things around Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: bring back compile macros Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: switch to quotes for import Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: add compiler error macro Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: add s390x detection in ggml-src Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: bring back compile definitions Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: undo cmakelists work Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * Revert "ggml-cpu: move s390x typedef to own header file" This reverts commit18d79e1a30. Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: remove typedefs.h Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: remove typedef from cmakelists Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: add ggml-impl.h future notes Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: add todo comment for future reference Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: clarify naming of dlf16 Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: remove unnecessary target compile definitions Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: move nnpa fp16->fp32 and fp32->fp16 to simd-mappings Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml: refactor fp32->fp16 and fp16->fp32 simd to ggml-cpu Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * docs: update broken huggingface link for s390x Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: fix duplicate func names during compile Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * Revert "ggml-cpu: fix duplicate func names during compile" This reverts commitfbb733451f. Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * Revert "ggml: refactor fp32->fp16 and fp16->fp32 simd to ggml-cpu" This reverts commitbd288e8fa5. Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml: refactor fp16<->fp32 simd to ggml-cpu Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: fix missing simd-mappings.h import in quants.c Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: fix missing simd-mappings.h within repack Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: fix amx mmq missing simd-mappings.h Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: attempt at fixing loongarch failing build Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: move nnpa together with other fp16<->fp32 simd Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: fix wrong refactor of ggml-base ref: https://github.com/ggml-org/llama.cpp/pull/14317#discussion_r2164176555 Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml: remove dependency on ggml-cpu from ggml-base Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: rename all fp16<->fp32 macros to prefix with ggml_cpu ref: https://github.com/ggml-org/llama.cpp/pull/14317#discussion_r2164449406 Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: remove mistaken fallback macro fallback logic was already implemented but i was too sleepy to realise Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml: move ggml_table_f32_f16 to ggml-cpu ref: https://github.com/ggml-org/llama.cpp/pull/14317#discussion_r2164775006 Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: move ggml_table_f32_f16 back to ggml-base due to ci failures Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * Revert "ggml-cpu: move ggml_table_f32_f16 back to ggml-base due to ci failures" This reverts commit32a3533564. Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * Revert "ggml: move ggml_table_f32_f16 to ggml-cpu" This reverts commit9e40d984ad. Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml: move ggml_table_f32_f16 to ggml-cpu ref: https://github.com/ggml-org/llama.cpp/pull/14317#discussion_r2164775006 Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> (cherry picked from commit9e40d984ad) * ggml: move ggml_table_f32_f16 to ggml-cpu.c Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: extern c ggml_table_f32_f16 + chore docs Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: dedup ggml_table_f32_f16 from simd-mappings.h we rely on the variable declaration in ggml-cpu.c instead Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * Revert "ggml-cpu: dedup ggml_table_f32_f16 from simd-mappings.h" This reverts commitf71b21d2f7. Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * ggml-cpu: bring back ggml_table_f32_f16 Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * Revert "ggml-cpu: bring back ggml_table_f32_f16" This reverts commit2dce119178. Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * fix ggml time initialization * fix f32_f16 table init * remove extra line --------- Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> Co-authored-by: slaren <slarengh@gmail.com>
This commit is contained in:
		| @@ -317,203 +317,81 @@ struct ggml_cgraph ggml_graph_view(struct ggml_cgraph * cgraph, int i0, int i1); | ||||
| GGML_API void * ggml_aligned_malloc(size_t size); | ||||
| GGML_API void ggml_aligned_free(void * ptr, size_t size); | ||||
|  | ||||
| // FP16 to FP32 conversion | ||||
| // FP16 <-> FP32 | ||||
| // ref: https://github.com/Maratyszcza/FP16 | ||||
|  | ||||
| // 16-bit float | ||||
| // on Arm, we use __fp16 | ||||
| // on x86, we use uint16_t | ||||
| // | ||||
| // for old CUDA compilers (<= 11), we use uint16_t: ref https://github.com/ggml-org/llama.cpp/pull/10616 | ||||
| // for     MUSA compilers        , we use uint16_t: ref https://github.com/ggml-org/llama.cpp/pull/11843 | ||||
| // | ||||
| #if defined(__ARM_NEON) && !(defined(__CUDACC__) && __CUDACC_VER_MAJOR__ <= 11) && !defined(__MUSACC__) | ||||
|     #define GGML_COMPUTE_FP16_TO_FP32(x) ggml_compute_fp16_to_fp32(x) | ||||
|     #define GGML_COMPUTE_FP32_TO_FP16(x) ggml_compute_fp32_to_fp16(x) | ||||
|  | ||||
|     #define GGML_FP16_TO_FP32(x) ggml_compute_fp16_to_fp32(x) | ||||
|  | ||||
|     static inline float ggml_compute_fp16_to_fp32(ggml_fp16_t h) { | ||||
|         __fp16 tmp; | ||||
|         memcpy(&tmp, &h, sizeof(ggml_fp16_t)); | ||||
|         return (float)tmp; | ||||
|     } | ||||
|  | ||||
|     static inline ggml_fp16_t ggml_compute_fp32_to_fp16(float f) { | ||||
|         ggml_fp16_t res; | ||||
|         __fp16 tmp = f; | ||||
|         memcpy(&res, &tmp, sizeof(ggml_fp16_t)); | ||||
|         return res; | ||||
|     } | ||||
|  | ||||
| #elif defined(__F16C__) | ||||
|  | ||||
|     #ifdef _MSC_VER | ||||
|         #define GGML_COMPUTE_FP16_TO_FP32(x) _mm_cvtss_f32(_mm_cvtph_ps(_mm_cvtsi32_si128(x))) | ||||
|         #define GGML_COMPUTE_FP32_TO_FP16(x) _mm_extract_epi16(_mm_cvtps_ph(_mm_set_ss(x), 0), 0) | ||||
|     #else | ||||
|         #define GGML_COMPUTE_FP16_TO_FP32(x) _cvtsh_ss(x) | ||||
|         #define GGML_COMPUTE_FP32_TO_FP16(x) _cvtss_sh(x, 0) | ||||
|     #endif | ||||
|  | ||||
| #elif defined(__POWER9_VECTOR__) | ||||
|  | ||||
|     #define GGML_COMPUTE_FP16_TO_FP32(x) ggml_compute_fp16_to_fp32(x) | ||||
|     #define GGML_COMPUTE_FP32_TO_FP16(x) ggml_compute_fp32_to_fp16(x) | ||||
|     /* the inline asm below is about 12% faster than the lookup method */ | ||||
|     #define GGML_FP16_TO_FP32(x) GGML_COMPUTE_FP16_TO_FP32(x) | ||||
|     #define GGML_FP32_TO_FP16(x) GGML_COMPUTE_FP32_TO_FP16(x) | ||||
|  | ||||
|     static inline float ggml_compute_fp16_to_fp32(ggml_fp16_t h) { | ||||
|         float f; | ||||
|         double d; | ||||
|         __asm__( | ||||
|             "mtfprd %0,%2\n" | ||||
|             "xscvhpdp %0,%0\n" | ||||
|             "frsp %1,%0\n" : | ||||
|             /* temp */ "=d"(d), | ||||
|             /* out */  "=f"(f): | ||||
|             /* in */   "r"(h)); | ||||
|         return f; | ||||
|     } | ||||
|  | ||||
|     static inline ggml_fp16_t ggml_compute_fp32_to_fp16(float f) { | ||||
|         double d; | ||||
|         ggml_fp16_t r; | ||||
|         __asm__( /* xscvdphp can work on double or single precision */ | ||||
|             "xscvdphp %0,%2\n" | ||||
|             "mffprd %1,%0\n" : | ||||
|             /* temp */ "=d"(d), | ||||
|             /* out */  "=r"(r): | ||||
|             /* in */   "f"(f)); | ||||
|         return r; | ||||
|     } | ||||
|  | ||||
| #elif defined(__riscv) && defined(__riscv_zfhmin) | ||||
|  | ||||
|     static inline float ggml_compute_fp16_to_fp32(ggml_fp16_t h) { | ||||
|         float f; | ||||
|         __asm__( | ||||
|             "fmv.h.x %[f], %[h]\n\t" | ||||
|             "fcvt.s.h %[f], %[f]" | ||||
|             : [f] "=&f" (f) | ||||
|             : [h] "r" (h) | ||||
|         ); | ||||
|         return f; | ||||
|     } | ||||
|  | ||||
|     static inline ggml_fp16_t ggml_compute_fp32_to_fp16(float f) { | ||||
|         ggml_fp16_t res; | ||||
|         __asm__( | ||||
|             "fcvt.h.s %[f], %[f]\n\t" | ||||
|             "fmv.x.h %[h], %[f]" | ||||
|             : [h] "=&r" (res) | ||||
|             : [f] "f" (f) | ||||
|         ); | ||||
|         return res; | ||||
|     } | ||||
|  | ||||
|     #define GGML_COMPUTE_FP16_TO_FP32(x) ggml_compute_fp16_to_fp32(x) | ||||
|     #define GGML_COMPUTE_FP32_TO_FP16(x) ggml_compute_fp32_to_fp16(x) | ||||
|     #define GGML_FP16_TO_FP32(x) GGML_COMPUTE_FP16_TO_FP32(x) | ||||
|     #define GGML_FP32_TO_FP16(x) GGML_COMPUTE_FP32_TO_FP16(x) | ||||
|  | ||||
| #else | ||||
|  | ||||
|     // FP16 <-> FP32 | ||||
|     // ref: https://github.com/Maratyszcza/FP16 | ||||
|  | ||||
|     static inline float fp32_from_bits(uint32_t w) { | ||||
|         union { | ||||
|             uint32_t as_bits; | ||||
|             float as_value; | ||||
|         } fp32; | ||||
|         fp32.as_bits = w; | ||||
|         return fp32.as_value; | ||||
|     } | ||||
|  | ||||
|     static inline uint32_t fp32_to_bits(float f) { | ||||
|         union { | ||||
|             float as_value; | ||||
|             uint32_t as_bits; | ||||
|         } fp32; | ||||
|         fp32.as_value = f; | ||||
|         return fp32.as_bits; | ||||
|     } | ||||
|  | ||||
|     static inline float ggml_compute_fp16_to_fp32(ggml_fp16_t h) { | ||||
|         const uint32_t w = (uint32_t) h << 16; | ||||
|         const uint32_t sign = w & UINT32_C(0x80000000); | ||||
|         const uint32_t two_w = w + w; | ||||
|  | ||||
|         const uint32_t exp_offset = UINT32_C(0xE0) << 23; | ||||
|     #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || defined(__GNUC__) && !defined(__STRICT_ANSI__)) && (!defined(__cplusplus) || __cplusplus >= 201703L) | ||||
|         const float exp_scale = 0x1.0p-112f; | ||||
|     #else | ||||
|         const float exp_scale = fp32_from_bits(UINT32_C(0x7800000)); | ||||
|     #endif | ||||
|         const float normalized_value = fp32_from_bits((two_w >> 4) + exp_offset) * exp_scale; | ||||
|  | ||||
|         const uint32_t magic_mask = UINT32_C(126) << 23; | ||||
|         const float magic_bias = 0.5f; | ||||
|         const float denormalized_value = fp32_from_bits((two_w >> 17) | magic_mask) - magic_bias; | ||||
|  | ||||
|         const uint32_t denormalized_cutoff = UINT32_C(1) << 27; | ||||
|         const uint32_t result = sign | | ||||
|             (two_w < denormalized_cutoff ? fp32_to_bits(denormalized_value) : fp32_to_bits(normalized_value)); | ||||
|         return fp32_from_bits(result); | ||||
|     } | ||||
|  | ||||
|     static inline ggml_fp16_t ggml_compute_fp32_to_fp16(float f) { | ||||
|     #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || defined(__GNUC__) && !defined(__STRICT_ANSI__)) && (!defined(__cplusplus) || __cplusplus >= 201703L) | ||||
|         const float scale_to_inf = 0x1.0p+112f; | ||||
|         const float scale_to_zero = 0x1.0p-110f; | ||||
|     #else | ||||
|         const float scale_to_inf = fp32_from_bits(UINT32_C(0x77800000)); | ||||
|         const float scale_to_zero = fp32_from_bits(UINT32_C(0x08800000)); | ||||
|     #endif | ||||
|         float base = (fabsf(f) * scale_to_inf) * scale_to_zero; | ||||
|  | ||||
|         const uint32_t w = fp32_to_bits(f); | ||||
|         const uint32_t shl1_w = w + w; | ||||
|         const uint32_t sign = w & UINT32_C(0x80000000); | ||||
|         uint32_t bias = shl1_w & UINT32_C(0xFF000000); | ||||
|         if (bias < UINT32_C(0x71000000)) { | ||||
|             bias = UINT32_C(0x71000000); | ||||
|         } | ||||
|  | ||||
|         base = fp32_from_bits((bias >> 1) + UINT32_C(0x07800000)) + base; | ||||
|         const uint32_t bits = fp32_to_bits(base); | ||||
|         const uint32_t exp_bits = (bits >> 13) & UINT32_C(0x00007C00); | ||||
|         const uint32_t mantissa_bits = bits & UINT32_C(0x00000FFF); | ||||
|         const uint32_t nonsign = exp_bits + mantissa_bits; | ||||
|         return (sign >> 16) | (shl1_w > UINT32_C(0xFF000000) ? UINT16_C(0x7E00) : nonsign); | ||||
|     } | ||||
|  | ||||
|     #define GGML_COMPUTE_FP16_TO_FP32(x) ggml_compute_fp16_to_fp32(x) | ||||
|     #define GGML_COMPUTE_FP32_TO_FP16(x) ggml_compute_fp32_to_fp16(x) | ||||
|  | ||||
| #endif // defined(__ARM_NEON) && !(defined(__CUDACC__) && __CUDACC_VER_MAJOR__ <= 11) && !defined(__MUSACC__) | ||||
|  | ||||
| // precomputed f32 table for f16 (256 KB) | ||||
| // defined in ggml.c, initialized in ggml_init() | ||||
| GGML_API float ggml_table_f32_f16[1 << 16]; | ||||
|  | ||||
| // On ARM NEON, it's quicker to directly convert x -> x instead of calling into ggml_lookup_fp16_to_fp32, | ||||
| // so we define GGML_FP16_TO_FP32 and GGML_FP32_TO_FP16 elsewhere for NEON. | ||||
| // This is also true for POWER9. | ||||
| #if !defined(GGML_FP16_TO_FP32) | ||||
| inline static float ggml_lookup_fp16_to_fp32(ggml_fp16_t f) { | ||||
|     uint16_t s; | ||||
|     memcpy(&s, &f, sizeof(uint16_t)); | ||||
|     return ggml_table_f32_f16[s]; | ||||
| static inline float fp32_from_bits(uint32_t w) { | ||||
|     union { | ||||
|         uint32_t as_bits; | ||||
|         float as_value; | ||||
|     } fp32; | ||||
|     fp32.as_bits = w; | ||||
|     return fp32.as_value; | ||||
| } | ||||
|  | ||||
| #define GGML_FP16_TO_FP32(x) ggml_lookup_fp16_to_fp32(x) | ||||
| #endif | ||||
| static inline uint32_t fp32_to_bits(float f) { | ||||
|     union { | ||||
|         float as_value; | ||||
|         uint32_t as_bits; | ||||
|     } fp32; | ||||
|     fp32.as_value = f; | ||||
|     return fp32.as_bits; | ||||
| } | ||||
|  | ||||
| #if !defined(GGML_FP32_TO_FP16) | ||||
| #define GGML_FP32_TO_FP16(x) GGML_COMPUTE_FP32_TO_FP16(x) | ||||
| static inline float ggml_compute_fp16_to_fp32(ggml_fp16_t h) { | ||||
|     const uint32_t w = (uint32_t) h << 16; | ||||
|     const uint32_t sign = w & UINT32_C(0x80000000); | ||||
|     const uint32_t two_w = w + w; | ||||
|  | ||||
|     const uint32_t exp_offset = UINT32_C(0xE0) << 23; | ||||
| #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || defined(__GNUC__) && !defined(__STRICT_ANSI__)) && (!defined(__cplusplus) || __cplusplus >= 201703L) | ||||
|     const float exp_scale = 0x1.0p-112f; | ||||
| #else | ||||
|     const float exp_scale = fp32_from_bits(UINT32_C(0x7800000)); | ||||
| #endif | ||||
|     const float normalized_value = fp32_from_bits((two_w >> 4) + exp_offset) * exp_scale; | ||||
|  | ||||
|     const uint32_t magic_mask = UINT32_C(126) << 23; | ||||
|     const float magic_bias = 0.5f; | ||||
|     const float denormalized_value = fp32_from_bits((two_w >> 17) | magic_mask) - magic_bias; | ||||
|  | ||||
|     const uint32_t denormalized_cutoff = UINT32_C(1) << 27; | ||||
|     const uint32_t result = sign | | ||||
|         (two_w < denormalized_cutoff ? fp32_to_bits(denormalized_value) : fp32_to_bits(normalized_value)); | ||||
|     return fp32_from_bits(result); | ||||
| } | ||||
|  | ||||
| static inline ggml_fp16_t ggml_compute_fp32_to_fp16(float f) { | ||||
| #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || defined(__GNUC__) && !defined(__STRICT_ANSI__)) && (!defined(__cplusplus) || __cplusplus >= 201703L) | ||||
|     const float scale_to_inf = 0x1.0p+112f; | ||||
|     const float scale_to_zero = 0x1.0p-110f; | ||||
| #else | ||||
|     const float scale_to_inf = fp32_from_bits(UINT32_C(0x77800000)); | ||||
|     const float scale_to_zero = fp32_from_bits(UINT32_C(0x08800000)); | ||||
| #endif | ||||
|     float base = (fabsf(f) * scale_to_inf) * scale_to_zero; | ||||
|  | ||||
|     const uint32_t w = fp32_to_bits(f); | ||||
|     const uint32_t shl1_w = w + w; | ||||
|     const uint32_t sign = w & UINT32_C(0x80000000); | ||||
|     uint32_t bias = shl1_w & UINT32_C(0xFF000000); | ||||
|     if (bias < UINT32_C(0x71000000)) { | ||||
|         bias = UINT32_C(0x71000000); | ||||
|     } | ||||
|  | ||||
|     base = fp32_from_bits((bias >> 1) + UINT32_C(0x07800000)) + base; | ||||
|     const uint32_t bits = fp32_to_bits(base); | ||||
|     const uint32_t exp_bits = (bits >> 13) & UINT32_C(0x00007C00); | ||||
|     const uint32_t mantissa_bits = bits & UINT32_C(0x00000FFF); | ||||
|     const uint32_t nonsign = exp_bits + mantissa_bits; | ||||
|     return (sign >> 16) | (shl1_w > UINT32_C(0xFF000000) ? UINT16_C(0x7E00) : nonsign); | ||||
| } | ||||
|  | ||||
| #define GGML_COMPUTE_FP16_TO_FP32(x) ggml_compute_fp16_to_fp32(x) | ||||
| #define GGML_COMPUTE_FP32_TO_FP16(x) ggml_compute_fp32_to_fp16(x) | ||||
|  | ||||
| #define GGML_FP16_TO_FP32(x) GGML_COMPUTE_FP16_TO_FP32(x) | ||||
| #define GGML_FP32_TO_FP16(x) GGML_COMPUTE_FP32_TO_FP16(x) | ||||
|  | ||||
| /** | ||||
|  * Converts brain16 to float32. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Aaron Teo
					Aaron Teo