#pragma once #include "ggml-metal-impl.h" #include #ifdef GGML_METAL_HAS_TENSOR #include #include #endif using namespace metal; #define MAX(x, y) ((x) > (y) ? (x) : (y)) #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define SWAP(x, y) { auto tmp = (x); (x) = (y); (y) = tmp; } #define PAD2(x, n) (((x) + (n) - 1) & ~((n) - 1)) #define FOR_UNROLL(x) _Pragma("clang loop unroll(full)") for (x) #define N_SIMDWIDTH 32 // assuming SIMD group size is 32 // ref: https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf // // cmd: // .../usr/bin/metal -dM -E -c ggml/src/ggml-metal/kernels/.metal // .../usr/bin/metal -dM -E -c -target air64-apple-ios14.0 ggml/src/ggml-metal/kernels/.metal // #if __METAL_VERSION__ < 310 && defined(GGML_METAL_HAS_BF16) #undef GGML_METAL_HAS_BF16 #endif #if defined(GGML_METAL_HAS_BF16) typedef matrix bfloat4x4; typedef matrix bfloat2x4; #endif constexpr constant static float kvalues_iq4nl_f[16] = { -127.f, -104.f, -83.f, -65.f, -49.f, -35.f, -22.f, -10.f, 1.f, 13.f, 25.f, 38.f, 53.f, 69.f, 89.f, 113.f }; constexpr constant static float kvalues_mxfp4_f[16] = { 0, .5f, 1.f, 1.5f, 2.f, 3.f, 4.f, 6.f, -0, -.5f, -1.f, -1.5f, -2.f, -3.f, -4.f, -6.f }; static inline int best_index_int8(int n, constant float * val, float x) { if (x <= val[0]) return 0; if (x >= val[n-1]) return n-1; int ml = 0, mu = n-1; while (mu-ml > 1) { int mav = (ml+mu)/2; if (x < val[mav]) mu = mav; else ml = mav; } return x - val[mu-1] < val[mu] - x ? mu-1 : mu; } static inline float e8m0_to_fp32(uint8_t x) { uint32_t bits; if (x == 0) { bits = 0x00400000; } else { bits = (uint32_t) x << 23; } return as_type(bits); } static inline float dot(float x, float y) { return x*y; } static inline float sum(float x) { return x; } static inline float sum(float4 x) { return x[0] + x[1] + x[2] + x[3]; } enum ggml_sort_order { GGML_SORT_ORDER_ASC, GGML_SORT_ORDER_DESC, }; constant float GELU_COEF_A = 0.044715f; constant float GELU_QUICK_COEF = -1.702f; constant float SQRT_2_OVER_PI = 0.79788456080286535587989211986876f; constant float SQRT_2_INV = 0.70710678118654752440084436210484f; // based on Abramowitz and Stegun formula 7.1.26 or similar Hastings' approximation // ref: https://www.johndcook.com/blog/python_erf/ constant float p_erf = 0.3275911f; constant float a1_erf = 0.254829592f; constant float a2_erf = -0.284496736f; constant float a3_erf = 1.421413741f; constant float a4_erf = -1.453152027f; constant float a5_erf = 1.061405429f; template inline T erf_approx(T x) { T sign_x = sign(x); x = fabs(x); T t = 1.0f / (1.0f + p_erf * x); T y = 1.0f - (((((a5_erf * t + a4_erf) * t) + a3_erf) * t + a2_erf) * t + a1_erf) * t * exp(-x * x); return sign_x * y; } template T elu_approx(T x); template<> inline float elu_approx(float x) { return (x > 0.f) ? x : (exp(x) - 1); } template<> inline float4 elu_approx(float4 x) { float4 res; res[0] = (x[0] > 0.0f) ? x[0] : (exp(x[0]) - 1.0f); res[1] = (x[1] > 0.0f) ? x[1] : (exp(x[1]) - 1.0f); res[2] = (x[2] > 0.0f) ? x[2] : (exp(x[2]) - 1.0f); res[3] = (x[3] > 0.0f) ? x[3] : (exp(x[3]) - 1.0f); return res; }