|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| #include <cuda_bf16.h>
|
| #include <cuda_pipeline_primitives.h>
|
| #include <math.h>
|
|
|
| #include "mak_kernels.h"
|
|
|
| #define BLOCK_THREADS 256
|
| #define MAX_HEAD_DIM 512
|
|
|
|
|
|
|
|
|
|
|
|
|
| #define GEMV_RING_STAGE_BYTES ((BLOCK_THREADS / 32) * 32 * 16)
|
|
|
| namespace mak {
|
|
|
| using bf16 = __nv_bfloat16;
|
|
|
| enum PhaseOp : int {
|
| OP_EMBED = 0,
|
| OP_GEMV = 1,
|
| OP_QKV_POST = 2,
|
| OP_ATTN = 3,
|
| OP_ARGMAX_PART = 4,
|
| OP_ARGMAX_FIN = 5,
|
| OP_KV_APPEND = 6,
|
| OP_NORMRES = 7,
|
| OP_PLEMIX = 8,
|
|
|
|
|
|
|
| OP_GEMV_PLAIN = 9,
|
| OP_NORMB = 10,
|
| OP_GLUB = 11,
|
| OP_ATTNFINB = 12,
|
| OP_GEMV_Q4 = 13,
|
| };
|
|
|
|
|
|
|
|
|
|
|
| __device__ __constant__ float NF4_CODE[16] = {
|
| -1.0f, -0.6961928009986877f, -0.5250730514526367f,
|
| -0.39491748809814453f, -0.28444138169288635f, -0.18477343022823334f,
|
| -0.09105003625154495f, 0.0f, 0.07958029955625534f, 0.16093020141124725f,
|
| 0.24611230194568634f, 0.33791524171829224f, 0.44070982933044434f,
|
| 0.5626170039176941f, 0.7229568362236023f, 1.0f};
|
|
|
| enum InputTransform : int {
|
| IT_NONE = 0,
|
| IT_RMSNORM = 1,
|
| IT_SWIGLU = 2,
|
| IT_ATTNFIN = 3,
|
| IT_RMSNORM_G = 4,
|
| IT_GELU_GLU = 5,
|
| };
|
|
|
| #define ITF_BASE_MASK 7
|
| #define ITF_REDUCE 8
|
| #define ITF_WRITEBACK 16
|
|
|
| enum Epilogue : int {
|
| EP_STORE = 0,
|
| EP_RESID = 1,
|
| EP_F32 = 2,
|
| EP_F32_AMAX = 3,
|
| EP_PARTIAL = 4,
|
| EP_GELU_PLE = 5,
|
| EP_F32_AMAX_CAP = 6,
|
| };
|
|
|
| #define ATTN_CHUNK 128
|
| #define NSLICE 4
|
|
|
|
|
|
|
|
|
|
|
|
|
| __device__ __forceinline__ float bits2f(long long v) {
|
| return __int_as_float((int)v);
|
| }
|
| __device__ __forceinline__ float bf2f(bf16 v) { return __bfloat162float(v); }
|
| __device__ __forceinline__ bf16 f2bf(float v) { return __float2bfloat16(v); }
|
|
|
|
|
| __device__ __forceinline__ float gelu_tanh_f(float x) {
|
| const float c = 0.7978845608028654f;
|
| const float t = tanhf(c * (x + 0.044715f * x * x * x));
|
| return 0.5f * x * (1.f + t);
|
| }
|
|
|
| __device__ __forceinline__ unsigned dyn_smem_size() {
|
| unsigned r;
|
| asm("mov.u32 %0, %%dynamic_smem_size;" : "=r"(r));
|
| return r;
|
| }
|
|
|
| __device__ __forceinline__ float warp_sum(float v) {
|
| for (int o = 16; o > 0; o >>= 1) v += __shfl_down_sync(0xffffffffu, v, o);
|
| return v;
|
| }
|
| __device__ __forceinline__ float warp_max(float v) {
|
| for (int o = 16; o > 0; o >>= 1)
|
| v = fmaxf(v, __shfl_down_sync(0xffffffffu, v, o));
|
| return v;
|
| }
|
| __device__ __forceinline__ unsigned long long warp_max_u64(unsigned long long v) {
|
| for (int o = 16; o > 0; o >>= 1) {
|
| unsigned long long w = __shfl_down_sync(0xffffffffu, v, o);
|
| v = (w > v) ? w : v;
|
| }
|
| return v;
|
| }
|
|
|
|
|
| __device__ float block_sum(float v, float* s_red) {
|
| const int lane = threadIdx.x & 31, w = threadIdx.x >> 5;
|
| v = warp_sum(v);
|
| if (lane == 0) s_red[w] = v;
|
| __syncthreads();
|
| const int nw = blockDim.x >> 5;
|
| v = (threadIdx.x < nw) ? s_red[threadIdx.x] : 0.f;
|
| if (w == 0) v = warp_sum(v);
|
| __syncthreads();
|
| return v;
|
| }
|
| __device__ float block_max(float v, float* s_red) {
|
| const int lane = threadIdx.x & 31, w = threadIdx.x >> 5;
|
| v = warp_max(v);
|
| if (lane == 0) s_red[w] = v;
|
| __syncthreads();
|
| const int nw = blockDim.x >> 5;
|
| v = (threadIdx.x < nw) ? s_red[threadIdx.x] : -INFINITY;
|
| if (w == 0) v = warp_max(v);
|
| __syncthreads();
|
| return v;
|
| }
|
| __device__ unsigned long long block_max_u64(unsigned long long v,
|
| unsigned long long* s_red) {
|
| const int lane = threadIdx.x & 31, w = threadIdx.x >> 5;
|
| v = warp_max_u64(v);
|
| if (lane == 0) s_red[w] = v;
|
| __syncthreads();
|
| const int nw = blockDim.x >> 5;
|
| v = (threadIdx.x < nw) ? s_red[threadIdx.x] : 0ull;
|
| if (w == 0) v = warp_max_u64(v);
|
| __syncthreads();
|
| return v;
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
| __device__ unsigned long long block_max_u64(unsigned long long v,
|
| unsigned long long* s_red);
|
| __device__ __forceinline__ unsigned long long amax_key(float v, unsigned idx);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| __device__ __forceinline__ int pm_of(int pos, int m, const int* pos_b,
|
| int step) {
|
| return (pos_b != nullptr) ? (pos_b[m] + step) : (pos + m);
|
| }
|
|
|
| __device__ void ph_embed(const long long* P, int pos, int M, int prompt_len,
|
| int step_slot, const int* pos_b) {
|
| const bf16* tab = reinterpret_cast<const bf16*>(P[2]);
|
| bf16* out = reinterpret_cast<bf16*>(P[3]);
|
| const unsigned long long* parts =
|
| reinterpret_cast<const unsigned long long*>(P[4]);
|
| const int* prompt = reinterpret_cast<const int*>(P[5]);
|
| const int* tok = reinterpret_cast<const int*>(P[6]);
|
| int* toks_out = reinterpret_cast<int*>(P[7]);
|
| const long long K = P[8];
|
|
|
| __shared__ int s_tok;
|
| __shared__ int s_tokb[8];
|
| const bool need_feedback = (pos + M - 1 >= prompt_len);
|
| if (pos_b != nullptr) {
|
|
|
| if (threadIdx.x < M) s_tokb[threadIdx.x] = tok[threadIdx.x];
|
| __syncthreads();
|
| } else if (need_feedback) {
|
| if (prompt_len >= 0 && parts != nullptr) {
|
| unsigned long long best = amax_key(-INFINITY, 0xFFFFFFFFu);
|
| for (int i = threadIdx.x; i < (int)gridDim.x; i += blockDim.x) {
|
| const unsigned long long kk = parts[i];
|
| best = (kk > best) ? kk : best;
|
| }
|
| __shared__ unsigned long long s64[32];
|
| best = block_max_u64(best, s64);
|
| if (threadIdx.x == 0) {
|
| const int idx = (int)(0xFFFFFFFFu - (unsigned)(best & 0xFFFFFFFFull));
|
| s_tok = idx;
|
| const int prev_slot = step_slot - M;
|
| if (toks_out != nullptr && prev_slot >= 0 && blockIdx.x == 0)
|
| toks_out[prev_slot] = idx;
|
| }
|
| } else {
|
| if (threadIdx.x == 0) s_tok = tok[0];
|
| }
|
| __syncthreads();
|
| }
|
|
|
| const float hsc = bits2f(P[14]);
|
| for (long long i = (long long)blockIdx.x * blockDim.x + threadIdx.x;
|
| i < (long long)M * K; i += (long long)gridDim.x * blockDim.x) {
|
| const int m = (int)(i / K);
|
| const long long k = i % K;
|
| const int pm = pos + m;
|
| const long long t =
|
| (pos_b != nullptr)
|
| ? (long long)s_tokb[m]
|
| : ((pm < prompt_len && prompt != nullptr)
|
| ? (long long)prompt[pm]
|
| : (long long)s_tok);
|
| out[i] = (hsc != 0.f) ? f2bf(bf2f(tab[t * K + k]) * hsc)
|
| : tab[t * K + k];
|
| }
|
|
|
|
|
|
|
| const bf16* ptab = reinterpret_cast<const bf16*>(P[1]);
|
| bf16* pout = reinterpret_cast<bf16*>(P[9]);
|
| if (ptab != nullptr && pout != nullptr && M == 1) {
|
| const long long PL = P[12];
|
| const float esc = bits2f(P[15]);
|
| const long long t = (pos < prompt_len && prompt != nullptr)
|
| ? (long long)prompt[pos]
|
| : (long long)s_tok;
|
| for (long long i = (long long)blockIdx.x * blockDim.x + threadIdx.x;
|
| i < PL; i += (long long)gridDim.x * blockDim.x)
|
| pout[i] = f2bf(bf2f(ptab[t * PL + i]) * esc);
|
| }
|
| }
|
|
|
| __device__ __forceinline__ unsigned long long amax_key(float v, unsigned idx) {
|
| unsigned u = __float_as_uint(v);
|
| u = (u & 0x80000000u) ? ~u : (u | 0x80000000u);
|
| return ((unsigned long long)u << 32) |
|
| (unsigned long long)(0xFFFFFFFFu - idx);
|
| }
|
|
|
|
|
|
|
|
|
| __device__ __forceinline__ float attn_finalize(const float* mpart, int h,
|
| int d, int D, int maxch,
|
| int nch, int nch_lo) {
|
| const float* base = mpart + ((long long)h * maxch) * (D + 2);
|
| float M = -INFINITY;
|
| for (int c = nch_lo; c < nch; ++c)
|
| M = fmaxf(M, base[(long long)c * (D + 2) + D]);
|
| float L = 0.f, acc = 0.f;
|
| for (int c = nch_lo; c < nch; ++c) {
|
| const float* pc = base + (long long)c * (D + 2);
|
| const float w = expf(pc[D] - M);
|
| L = fmaf(pc[D + 1], w, L);
|
| acc = fmaf(pc[d], w, acc);
|
| }
|
| return bf2f(f2bf(acc / L));
|
| }
|
|
|
| __device__ __forceinline__ float mk_load_x(const bf16* x, const bf16* gamma,
|
| long long k, long long K, int itrans,
|
| float inv, const float* part,
|
| int D, int maxch, int nch) {
|
| if (itrans == IT_RMSNORM)
|
|
|
|
|
| return bf2f(f2bf(bf2f(gamma[k]) * bf2f(f2bf(bf2f(x[k]) * inv))));
|
| if (itrans == IT_SWIGLU) {
|
|
|
| const float g = bf2f(x[k]);
|
| const float sig = 1.f / (1.f + expf(-g));
|
| const float sg = bf2f(f2bf(g * sig));
|
| return bf2f(f2bf(sg * bf2f(x[K + k])));
|
| }
|
| if (itrans == IT_ATTNFIN)
|
| return attn_finalize(part, (int)(k / D), (int)(k % D), D, maxch, nch,
|
| 0);
|
| return bf2f(x[k]);
|
| }
|
|
|
|
|
| __device__ __forceinline__ void gemv_store(const long long* P, int epi,
|
| long long N, const bf16* resid,
|
| int srcm, long long row, float a) {
|
| if (epi == EP_RESID)
|
| reinterpret_cast<bf16*>(P[3])[(long long)srcm * N + row] =
|
| f2bf(bf2f(resid[(long long)srcm * N + row]) + a);
|
| else if (epi == EP_F32)
|
| reinterpret_cast<float*>(P[3])[(long long)srcm * N + row] = a;
|
| else if (epi == EP_GELU_PLE) {
|
|
|
|
|
| const bf16* ple = reinterpret_cast<const bf16*>(P[6]);
|
| const float g = bf2f(f2bf(a));
|
| const float act = bf2f(f2bf(gelu_tanh_f(g)));
|
| reinterpret_cast<bf16*>(P[3])[(long long)srcm * N + row] =
|
| f2bf(act * bf2f(ple[row]));
|
| } else
|
| reinterpret_cast<bf16*>(P[3])[(long long)srcm * N + row] = f2bf(a);
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
| template <int NB>
|
| __device__ void ph_gemv(const long long* P, int pos, int M, int rs,
|
| const int* pos_b, int step) {
|
| const bf16* W = reinterpret_cast<const bf16*>(P[2]);
|
| const bf16* gamma = reinterpret_cast<const bf16*>(P[4]);
|
| const bf16* resid = reinterpret_cast<const bf16*>(P[5]);
|
| const long long N = P[7], K = P[8];
|
| const int itrans = ((int)P[9]) & ITF_BASE_MASK;
|
| const bool tiled = ((P[9] >> 20) & 1) != 0;
|
| const int epi = (int)P[10];
|
| const int mmode = ((int)P[12]) & 0xFFFF;
|
| const int chbits = (int)(P[12] >> 16) & 0xFFFF;
|
| const int CH = (chbits > 0 && chbits <= ATTN_CHUNK) ? chbits : ATTN_CHUNK;
|
| const float eps = bits2f(P[14]);
|
| const float* part = reinterpret_cast<const float*>(P[1]);
|
| const bf16* xin = reinterpret_cast<const bf16*>(P[1]);
|
| const int D = (int)P[13];
|
| const int maxch = (int)(P[15] & 0xFFFF);
|
| const int fin_win = (int)((P[15] >> 16) & 0xFFFF);
|
|
|
|
|
|
|
| const int m0 = (mmode && pos_b == nullptr) ? (M - 1) : 0;
|
| const int Ma = M - m0;
|
|
|
|
|
| extern __shared__ unsigned char smem_raw[];
|
| int4* rng = reinterpret_cast<int4*>(smem_raw);
|
| bf16* xs = reinterpret_cast<bf16*>(
|
| smem_raw + (long long)rs * GEMV_RING_STAGE_BYTES);
|
| __shared__ float s_red[32];
|
| __shared__ float s_scale;
|
| __shared__ unsigned long long s64[32];
|
| __shared__ float s_fine[1024 + 128];
|
|
|
| const int lane = threadIdx.x & 31;
|
| const int wib = threadIdx.x >> 5;
|
|
|
|
|
|
|
|
|
| const long long gwarp =
|
| ((long long)blockIdx.x * blockDim.x + threadIdx.x) >> 5;
|
| const long long nwarps = ((long long)gridDim.x * blockDim.x) >> 5;
|
| const int rmask = rs - 1;
|
| int4* ringw = rng + (wib * rs) * 32 + lane;
|
| const long long kbase = (long long)lane * 8;
|
| const long long ntiles = (kbase < K) ? (K - kbase + 255) / 256 : 0;
|
| long long irow = gwarp, itile = 0;
|
| long long ig = 0, cg = 0;
|
|
|
|
|
|
|
|
|
|
|
| const long long K8 = K >> 3;
|
| auto issue_one = [&]() {
|
| if (irow < N && ntiles > 0) {
|
| const bf16* src =
|
| tiled ? W + (((irow >> 3) * K8 + (kbase >> 3) + itile * 32) << 6) +
|
| ((irow & 7) << 3)
|
| : W + irow * K + kbase + itile * 256;
|
| __pipeline_memcpy_async(ringw + ((int)ig & rmask) * 32, src, 16);
|
| __pipeline_commit();
|
| ++ig;
|
| if (++itile == ntiles) {
|
| itile = 0;
|
| irow += nwarps;
|
| }
|
| }
|
| };
|
| for (int i = 0; i < rs; ++i) issue_one();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| {
|
| for (int m = 0; m < Ma; ++m) {
|
| const int srcm = m0 + m;
|
| const long long G = K / 8;
|
| if (itrans == IT_RMSNORM) {
|
| const bf16* xr = xin + (long long)srcm * K;
|
| float ss = 0.f;
|
| for (long long g = threadIdx.x; g < G; g += blockDim.x) {
|
| const int4 x4 = *reinterpret_cast<const int4*>(xr + g * 8);
|
| *reinterpret_cast<int4*>(xs + (long long)m * K + g * 8) = x4;
|
| const __nv_bfloat162* xp =
|
| reinterpret_cast<const __nv_bfloat162*>(&x4);
|
| #pragma unroll
|
| for (int j = 0; j < 4; ++j) {
|
| const float lo = __low2float(xp[j]);
|
| const float hi = __high2float(xp[j]);
|
| ss += lo * lo;
|
| ss += hi * hi;
|
| }
|
| }
|
| ss = block_sum(ss, s_red);
|
| if (threadIdx.x == 0) s_scale = rsqrtf(ss / (float)K + eps);
|
| __syncthreads();
|
| const float inv = s_scale;
|
| for (long long g = threadIdx.x; g < G; g += blockDim.x) {
|
| bf16* xsp = xs + (long long)m * K + g * 8;
|
| int4 x4 = *reinterpret_cast<const int4*>(xsp);
|
| const int4 g4 = *reinterpret_cast<const int4*>(gamma + g * 8);
|
| __nv_bfloat162* xp = reinterpret_cast<__nv_bfloat162*>(&x4);
|
| const __nv_bfloat162* gp =
|
| reinterpret_cast<const __nv_bfloat162*>(&g4);
|
| #pragma unroll
|
| for (int j = 0; j < 4; ++j) {
|
| xp[j].x = f2bf(__low2float(gp[j]) *
|
| bf2f(f2bf(__low2float(xp[j]) * inv)));
|
| xp[j].y = f2bf(__high2float(gp[j]) *
|
| bf2f(f2bf(__high2float(xp[j]) * inv)));
|
| }
|
| *reinterpret_cast<int4*>(xsp) = x4;
|
| }
|
| __syncthreads();
|
| } else if (itrans == IT_RMSNORM_G) {
|
|
|
| const bf16* xr = xin + (long long)srcm * K;
|
| float ss = 0.f;
|
| for (long long g = threadIdx.x; g < G; g += blockDim.x) {
|
| const int4 x4 = *reinterpret_cast<const int4*>(xr + g * 8);
|
| *reinterpret_cast<int4*>(xs + (long long)m * K + g * 8) = x4;
|
| const __nv_bfloat162* xp =
|
| reinterpret_cast<const __nv_bfloat162*>(&x4);
|
| #pragma unroll
|
| for (int j = 0; j < 4; ++j) {
|
| const float lo = __low2float(xp[j]);
|
| const float hi = __high2float(xp[j]);
|
| ss += lo * lo;
|
| ss += hi * hi;
|
| }
|
| }
|
| ss = block_sum(ss, s_red);
|
| if (threadIdx.x == 0) s_scale = rsqrtf(ss / (float)K + eps);
|
| __syncthreads();
|
| const float inv = s_scale;
|
| for (long long g = threadIdx.x; g < G; g += blockDim.x) {
|
| bf16* xsp = xs + (long long)m * K + g * 8;
|
| int4 x4 = *reinterpret_cast<const int4*>(xsp);
|
| const int4 g4 = *reinterpret_cast<const int4*>(gamma + g * 8);
|
| __nv_bfloat162* xp = reinterpret_cast<__nv_bfloat162*>(&x4);
|
| const __nv_bfloat162* gp =
|
| reinterpret_cast<const __nv_bfloat162*>(&g4);
|
| #pragma unroll
|
| for (int j = 0; j < 4; ++j) {
|
| xp[j].x = f2bf((__low2float(xp[j]) * inv) * __low2float(gp[j]));
|
| xp[j].y =
|
| f2bf((__high2float(xp[j]) * inv) * __high2float(gp[j]));
|
| }
|
| *reinterpret_cast<int4*>(xsp) = x4;
|
| }
|
| __syncthreads();
|
| } else if (itrans == IT_GELU_GLU) {
|
|
|
| const bf16* xr = xin + (long long)srcm * 2 * K;
|
| for (long long g = threadIdx.x; g < G; g += blockDim.x) {
|
| const int4 g4 = *reinterpret_cast<const int4*>(xr + g * 8);
|
| const int4 u4 = *reinterpret_cast<const int4*>(xr + K + g * 8);
|
| int4 o4;
|
| const __nv_bfloat162* gp =
|
| reinterpret_cast<const __nv_bfloat162*>(&g4);
|
| const __nv_bfloat162* up =
|
| reinterpret_cast<const __nv_bfloat162*>(&u4);
|
| __nv_bfloat162* op = reinterpret_cast<__nv_bfloat162*>(&o4);
|
| #pragma unroll
|
| for (int j = 0; j < 4; ++j) {
|
| {
|
| const float gv = __low2float(gp[j]);
|
| const float act = bf2f(f2bf(gelu_tanh_f(gv)));
|
| op[j].x = f2bf(act * __low2float(up[j]));
|
| }
|
| {
|
| const float gv = __high2float(gp[j]);
|
| const float act = bf2f(f2bf(gelu_tanh_f(gv)));
|
| op[j].y = f2bf(act * __high2float(up[j]));
|
| }
|
| }
|
| *reinterpret_cast<int4*>(xs + (long long)m * K + g * 8) = o4;
|
| }
|
| } else if (itrans == IT_SWIGLU) {
|
| const bf16* xr = xin + (long long)srcm * 2 * K;
|
| for (long long g = threadIdx.x; g < G; g += blockDim.x) {
|
| const int4 g4 = *reinterpret_cast<const int4*>(xr + g * 8);
|
| const int4 u4 = *reinterpret_cast<const int4*>(xr + K + g * 8);
|
| int4 o4;
|
| const __nv_bfloat162* gp =
|
| reinterpret_cast<const __nv_bfloat162*>(&g4);
|
| const __nv_bfloat162* up =
|
| reinterpret_cast<const __nv_bfloat162*>(&u4);
|
| __nv_bfloat162* op = reinterpret_cast<__nv_bfloat162*>(&o4);
|
| #pragma unroll
|
| for (int j = 0; j < 4; ++j) {
|
| {
|
| const float gv = __low2float(gp[j]);
|
| const float sig = 1.f / (1.f + expf(-gv));
|
| const float sg = bf2f(f2bf(gv * sig));
|
| op[j].x = f2bf(sg * __low2float(up[j]));
|
| }
|
| {
|
| const float gv = __high2float(gp[j]);
|
| const float sig = 1.f / (1.f + expf(-gv));
|
| const float sg = bf2f(f2bf(gv * sig));
|
| op[j].y = f2bf(sg * __high2float(up[j]));
|
| }
|
| }
|
| *reinterpret_cast<int4*>(xs + (long long)m * K + g * 8) = o4;
|
| }
|
| } else if (itrans == IT_ATTNFIN) {
|
| const int pm = pm_of(pos, srcm, pos_b, step);
|
| const int nch = (pm + CH) / CH;
|
| const int s_lo = (fin_win > 0 && pm + 1 > fin_win)
|
| ? pm + 1 - fin_win : 0;
|
| const int nch_lo = s_lo / CH;
|
| const float* mpart =
|
| part + (long long)srcm * ((long long)P[11] * maxch * (D + 2));
|
| const int Hq_ = (int)P[11];
|
| if (Hq_ * nch <= 1024 && Hq_ <= 128) {
|
|
|
|
|
|
|
|
|
| float* ew = s_fine;
|
| float* lw = s_fine + 1024;
|
| for (int h = threadIdx.x; h < Hq_; h += blockDim.x) {
|
| const float* base = mpart + ((long long)h * maxch) * (D + 2);
|
| float Mx = -INFINITY;
|
| for (int c = nch_lo; c < nch; ++c)
|
| Mx = fmaxf(Mx, base[(long long)c * (D + 2) + D]);
|
| float L = 0.f;
|
| for (int c = nch_lo; c < nch; ++c) {
|
| const float* pc = base + (long long)c * (D + 2);
|
| const float w = expf(pc[D] - Mx);
|
| ew[h * nch + c] = w;
|
| L = fmaf(pc[D + 1], w, L);
|
| }
|
| lw[h] = L;
|
| }
|
| __syncthreads();
|
| if (D % 4 == 0) {
|
|
|
|
|
|
|
| for (long long g = threadIdx.x; g < K / 4; g += blockDim.x) {
|
| const long long k = g * 4;
|
| const int h = (int)(k / D), d0 = (int)(k % D);
|
| const float* base = mpart + ((long long)h * maxch) * (D + 2);
|
| float a0 = 0.f, a1 = 0.f, a2 = 0.f, a3 = 0.f;
|
| for (int c = nch_lo; c < nch; ++c) {
|
| const float* pc = base + (long long)c * (D + 2) + d0;
|
| const float2 pa = *reinterpret_cast<const float2*>(pc);
|
| const float2 pb = *reinterpret_cast<const float2*>(pc + 2);
|
| const float w = ew[h * nch + c];
|
| a0 = fmaf(pa.x, w, a0);
|
| a1 = fmaf(pa.y, w, a1);
|
| a2 = fmaf(pb.x, w, a2);
|
| a3 = fmaf(pb.y, w, a3);
|
| }
|
| const float L = lw[h];
|
| bf16* xp = xs + (long long)m * K + k;
|
| xp[0] = f2bf(bf2f(f2bf(a0 / L)));
|
| xp[1] = f2bf(bf2f(f2bf(a1 / L)));
|
| xp[2] = f2bf(bf2f(f2bf(a2 / L)));
|
| xp[3] = f2bf(bf2f(f2bf(a3 / L)));
|
| }
|
| } else {
|
| for (long long k = threadIdx.x; k < K; k += blockDim.x) {
|
| const int h = (int)(k / D), d = (int)(k % D);
|
| const float* base = mpart + ((long long)h * maxch) * (D + 2);
|
| float acc = 0.f;
|
| for (int c = nch_lo; c < nch; ++c)
|
| acc = fmaf(base[(long long)c * (D + 2) + d],
|
| ew[h * nch + c], acc);
|
| xs[(long long)m * K + k] = f2bf(bf2f(f2bf(acc / lw[h])));
|
| }
|
| }
|
| __syncthreads();
|
| } else {
|
| for (long long k = threadIdx.x; k < K; k += blockDim.x)
|
| xs[(long long)m * K + k] = f2bf(attn_finalize(
|
| mpart, (int)(k / D), (int)(k % D), D, maxch, nch, nch_lo));
|
| }
|
| } else {
|
| const bf16* xr = xin + (long long)srcm * K;
|
| for (long long g = threadIdx.x; g < G; g += blockDim.x)
|
| *reinterpret_cast<int4*>(xs + (long long)m * K + g * 8) =
|
| *reinterpret_cast<const int4*>(xr + g * 8);
|
| }
|
| }
|
| __syncthreads();
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| unsigned long long best = amax_key(-INFINITY, 0xFFFFFFFFu);
|
| {
|
| for (long long row = gwarp; row < N; row += nwarps) {
|
| float acc[NB];
|
| #pragma unroll
|
| for (int m = 0; m < NB; ++m) acc[m] = 0.f;
|
| auto consume = [&](const int4& w4, long long t) {
|
| const long long k = kbase + t * 256;
|
| const __nv_bfloat162* wp =
|
| reinterpret_cast<const __nv_bfloat162*>(&w4);
|
| #pragma unroll
|
| for (int m = 0; m < NB; ++m) {
|
| if (m < Ma) {
|
| const __nv_bfloat162* xp =
|
| reinterpret_cast<const __nv_bfloat162*>(xs +
|
| (long long)m * K + k);
|
| #pragma unroll
|
| for (int j = 0; j < 4; ++j) {
|
| acc[m] = fmaf(__low2float(wp[j]), __low2float(xp[j]), acc[m]);
|
| acc[m] = fmaf(__high2float(wp[j]), __high2float(xp[j]),
|
| acc[m]);
|
| }
|
| }
|
| }
|
| };
|
| for (long long t = 0; t < ntiles; ++t) {
|
| __pipeline_wait_prior((int)(ig - cg - 1));
|
| const int4 w4 = ringw[((int)cg & rmask) * 32];
|
| ++cg;
|
| issue_one();
|
| consume(w4, t);
|
| }
|
| #pragma unroll
|
| for (int m = 0; m < NB; ++m) {
|
| if (m < Ma) {
|
| const float a = warp_sum(acc[m]);
|
| if (lane == 0) {
|
| const int srcm = m0 + m;
|
| if (epi == EP_F32_AMAX) {
|
| reinterpret_cast<float*>(P[3])[row] = a;
|
| const unsigned long long kk = amax_key(bf2f(f2bf(a)),
|
| (unsigned)row);
|
| best = (kk > best) ? kk : best;
|
| } else if (epi == EP_F32_AMAX_CAP) {
|
|
|
| const float cap = bits2f(P[15]);
|
| const bf16 t1 = f2bf(a);
|
| const bf16 t2 = f2bf(bf2f(t1) / cap);
|
| const bf16 t3 = f2bf(tanhf(bf2f(t2)));
|
| const float v = bf2f(f2bf(bf2f(t3) * cap));
|
| reinterpret_cast<float*>(P[3])[row] = v;
|
| const unsigned long long kk = amax_key(v, (unsigned)row);
|
| best = (kk > best) ? kk : best;
|
| } else {
|
| gemv_store(P, epi, N, resid, srcm, row, a);
|
| }
|
| }
|
| }
|
| }
|
| }
|
| }
|
| if (epi == EP_F32_AMAX || epi == EP_F32_AMAX_CAP) {
|
| __syncthreads();
|
| best = block_max_u64(best, s64);
|
| if (threadIdx.x == 0)
|
| reinterpret_cast<unsigned long long*>(P[6])[blockIdx.x] = best;
|
| }
|
| }
|
|
|
|
|
|
|
| __device__ void kv_norm_rope_append(const bf16* qkv, bf16* kc, bf16* vc,
|
| const bf16* knw, int qk_flag, float eps,
|
| const float* invf, int Hq, int Hkv, int kvh,
|
| int D, int pm, float* s_red,
|
| float* s_inv, float* hbuf, float ascale) {
|
| const int half = D >> 1;
|
| const bf16* ksrc = qkv + (long long)(Hq + kvh) * D;
|
| const bf16* vsrc = qkv + (long long)(Hq + Hkv + kvh) * D;
|
| if (qk_flag & 1) {
|
| float ss = 0.f;
|
| for (int d = threadIdx.x; d < D; d += blockDim.x) {
|
| const float x = bf2f(ksrc[d]);
|
| ss += x * x;
|
| }
|
| ss = block_sum(ss, s_red);
|
| if (threadIdx.x == 0) *s_inv = rsqrtf(ss / (float)D + eps);
|
| __syncthreads();
|
| for (int d = threadIdx.x; d < D; d += blockDim.x)
|
| hbuf[d] = (qk_flag & 2)
|
| ? bf2f(f2bf((bf2f(ksrc[d]) * (*s_inv)) * bf2f(knw[d])))
|
| : bf2f(f2bf(bf2f(knw[d]) *
|
| bf2f(f2bf(bf2f(ksrc[d]) * (*s_inv)))));
|
| }
|
|
|
|
|
| if (qk_flag & 1) __syncthreads();
|
| bf16* krow = kc + (long long)pm * D;
|
| bf16* vrow = vc + (long long)pm * D;
|
| for (int d = threadIdx.x; d < half; d += blockDim.x) {
|
| const float ang = (float)pm * invf[d];
|
| const float c = bf2f(f2bf(cosf(ang) * ascale));
|
| const float s = bf2f(f2bf(sinf(ang) * ascale));
|
| const float x1 = (qk_flag & 1) ? hbuf[d] : bf2f(ksrc[d]);
|
| const float x2 = (qk_flag & 1) ? hbuf[d + half] : bf2f(ksrc[d + half]);
|
| krow[d] = f2bf(bf2f(f2bf(x1 * c)) + bf2f(f2bf(-x2 * s)));
|
| krow[d + half] = f2bf(bf2f(f2bf(x2 * c)) + bf2f(f2bf(x1 * s)));
|
| }
|
| if (qk_flag & 4) {
|
|
|
| float ss = 0.f;
|
| for (int d = threadIdx.x; d < D; d += blockDim.x) {
|
| const float x = bf2f(vsrc[d]);
|
| ss += x * x;
|
| }
|
| ss = block_sum(ss, s_red);
|
| if (threadIdx.x == 0) *s_inv = rsqrtf(ss / (float)D + eps);
|
| __syncthreads();
|
| for (int d = threadIdx.x; d < D; d += blockDim.x)
|
| vrow[d] = f2bf(bf2f(vsrc[d]) * (*s_inv));
|
| } else {
|
| for (int d = threadIdx.x; d < D; d += blockDim.x) vrow[d] = vsrc[d];
|
| }
|
| __threadfence_block();
|
| __syncthreads();
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| __device__ void ph_attn(const long long* P, int pos, int M,
|
| const int* pos_b, int step, long long kv_bstride) {
|
| const long long max_seq = P[7];
|
|
|
|
|
| const int qk_flag = ((int)P[8]) & 0xFFFF;
|
| const int win = (int)((P[8] >> 16) & 0xFFFFFFFFll);
|
| const float eps = bits2f(P[9]);
|
| const float* invf = reinterpret_cast<const float*>(P[10]);
|
| const int Hq = (int)P[11], Hkv = ((int)P[12]) & 0xFFFF;
|
| const int D = (int)P[13];
|
|
|
|
|
| const int chbits = (int)(P[12] >> 16) & 0xFFFF;
|
| const int CH = (chbits > 0 && chbits <= ATTN_CHUNK) ? chbits : ATTN_CHUNK;
|
| const float scale = bits2f(P[14]);
|
| const int maxch = (int)(P[15] & 0xFFFF);
|
|
|
| const int asbits = (int)(P[15] >> 32);
|
| const float ascale = (asbits != 0) ? __int_as_float(asbits) : 1.0f;
|
| const int rep = Hq / Hkv;
|
| const long long KT = (long long)(Hq + 2 * Hkv) * D;
|
|
|
| const bf16* qnw = reinterpret_cast<const bf16*>(P[5]);
|
| const bf16* knw = reinterpret_cast<const bf16*>(P[6]);
|
|
|
| __shared__ float qs[MAX_HEAD_DIM];
|
| __shared__ float hbuf[MAX_HEAD_DIM];
|
| __shared__ float sc[ATTN_CHUNK];
|
| __shared__ float pv[BLOCK_THREADS];
|
| __shared__ float s_red[32];
|
| __shared__ float s_inv, s_m;
|
|
|
|
|
|
|
|
|
| int pm_max = pos + M - 1;
|
| if (pos_b != nullptr) {
|
| int mx = pos_b[0];
|
| for (int m = 1; m < M; ++m) mx = (pos_b[m] > mx) ? pos_b[m] : mx;
|
| pm_max = mx + step;
|
| }
|
| const int nch_max = (pm_max + 1 + CH - 1) / CH;
|
| {
|
| const int total = M * Hq * nch_max;
|
| for (int v = blockIdx.x; v < total; v += gridDim.x) {
|
| const int m = v / (Hq * nch_max);
|
| const int rem = v % (Hq * nch_max);
|
| const int head = rem / nch_max;
|
| const int ch = rem % nch_max;
|
| const int pm = pm_of(pos, m, pos_b, step);
|
| const int S = pm + 1;
|
| const int nch = (S + CH - 1) / CH;
|
| if (ch >= nch) continue;
|
| const int s_lo = (win > 0 && S > win) ? S - win : 0;
|
| if (ch < s_lo / CH) continue;
|
| const int own_ch = pm / CH;
|
| const bf16* qkv =
|
| reinterpret_cast<const bf16*>(P[1]) + (long long)m * KT;
|
| float* partm = reinterpret_cast<float*>(P[4]) +
|
| (long long)m * ((long long)Hq * maxch * (D + 2));
|
| const int kvh = head / rep;
|
| const long long kvb = (pos_b != nullptr) ? (long long)m * kv_bstride : 0;
|
| bf16* kc = reinterpret_cast<bf16*>(P[2]) + kvb +
|
| (long long)kvh * max_seq * D;
|
| bf16* vc = reinterpret_cast<bf16*>(P[3]) + kvb +
|
| (long long)kvh * max_seq * D;
|
| float* part = partm + ((long long)head * maxch + ch) * (D + 2);
|
| const int half = D >> 1;
|
|
|
|
|
|
|
|
|
|
|
| if ((M == 1 || pos_b != nullptr) && ch == own_ch && !(qk_flag & 8)) {
|
| kv_norm_rope_append(qkv, kc, vc, knw, qk_flag, eps, invf, Hq, Hkv,
|
| kvh, D, pm, s_red, &s_inv, hbuf, ascale);
|
| }
|
|
|
| const int s0 = ch * CH;
|
| const int s1 = (s0 + CH < S) ? s0 + CH : S;
|
| const int cn = s1 - s0;
|
| const int si0 = (s0 < s_lo) ? (s_lo - s0) : 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
| extern __shared__ unsigned char smem_raw[];
|
| bf16* ks_sh = reinterpret_cast<bf16*>(smem_raw);
|
| bf16* vs_sh = ks_sh + (long long)CH * D;
|
| const bool kv_staged =
|
| (D % 8 == 0) &&
|
| (2u * (unsigned)CH * (unsigned)D * 2u <= dyn_smem_size());
|
| if (kv_staged) {
|
| const int ncpy = cn * D / 8;
|
| for (int i = threadIdx.x; i < ncpy; i += blockDim.x)
|
| __pipeline_memcpy_async(
|
| ks_sh + (long long)i * 8,
|
| kc + (long long)s0 * D + (long long)i * 8, 16);
|
| for (int i = threadIdx.x; i < ncpy; i += blockDim.x)
|
| __pipeline_memcpy_async(
|
| vs_sh + (long long)i * 8,
|
| vc + (long long)s0 * D + (long long)i * 8, 16);
|
| __pipeline_commit();
|
| }
|
|
|
|
|
| {
|
| const bf16* q = qkv + (long long)head * D;
|
| if (qk_flag & 1) {
|
| float ss = 0.f;
|
| for (int d = threadIdx.x; d < D; d += blockDim.x) {
|
| const float x = bf2f(q[d]);
|
| ss += x * x;
|
| }
|
| ss = block_sum(ss, s_red);
|
| if (threadIdx.x == 0) s_inv = rsqrtf(ss / (float)D + eps);
|
| __syncthreads();
|
| for (int d = threadIdx.x; d < D; d += blockDim.x)
|
| hbuf[d] = (qk_flag & 2)
|
| ? bf2f(f2bf((bf2f(q[d]) * s_inv) * bf2f(qnw[d])))
|
| : bf2f(f2bf(bf2f(qnw[d]) *
|
| bf2f(f2bf(bf2f(q[d]) * s_inv))));
|
| }
|
|
|
|
|
| if (qk_flag & 1) __syncthreads();
|
| for (int d = threadIdx.x; d < half; d += blockDim.x) {
|
| const float ang = (float)pm * invf[d];
|
| const float c = bf2f(f2bf(cosf(ang) * ascale));
|
| const float s = bf2f(f2bf(sinf(ang) * ascale));
|
| const float x1 = (qk_flag & 1) ? hbuf[d] : bf2f(q[d]);
|
| const float x2 =
|
| (qk_flag & 1) ? hbuf[d + half] : bf2f(q[d + half]);
|
| qs[d] = bf2f(f2bf(bf2f(f2bf(x1 * c)) + bf2f(f2bf(-x2 * s))));
|
| qs[d + half] = bf2f(f2bf(bf2f(f2bf(x2 * c)) + bf2f(f2bf(x1 * s))));
|
| }
|
| if (kv_staged) __pipeline_wait_prior(0);
|
| __syncthreads();
|
| }
|
|
|
|
|
|
|
| const int wid = threadIdx.x >> 5, lane = threadIdx.x & 31;
|
| const int nw = blockDim.x >> 5;
|
| for (int si = wid; si < cn; si += nw) {
|
| if (si < si0) continue;
|
| const bf16* kr = kv_staged ? ks_sh + (long long)si * D
|
| : kc + (long long)(s0 + si) * D;
|
| float acc = 0.f;
|
| for (int d = lane; d < D; d += 32) acc = fmaf(qs[d], bf2f(kr[d]), acc);
|
| acc = warp_sum(acc);
|
| if (lane == 0) {
|
| float x = bf2f(f2bf(acc));
|
| sc[si] = bf2f(f2bf(x * scale));
|
| }
|
| }
|
| __syncthreads();
|
|
|
| float mx = -INFINITY;
|
| for (int si = threadIdx.x; si < cn; si += blockDim.x)
|
| if (si >= si0) mx = fmaxf(mx, sc[si]);
|
| mx = block_max(mx, s_red);
|
| if (threadIdx.x == 0) s_m = mx;
|
| __syncthreads();
|
|
|
| float lsum = 0.f;
|
| for (int si = threadIdx.x; si < cn; si += blockDim.x) {
|
| if (si < si0) continue;
|
| const float p = expf(sc[si] - s_m);
|
| sc[si] = p;
|
| lsum += p;
|
| }
|
| lsum = block_sum(lsum, s_red);
|
| __syncthreads();
|
|
|
|
|
|
|
|
|
| const int NG = (BLOCK_THREADS / D < 8) ? BLOCK_THREADS / D : 8;
|
| if (NG > 1 && cn >= 64) {
|
| const int g = threadIdx.x / D;
|
| const int d = threadIdx.x - g * D;
|
| if (g < NG) {
|
| const int csz = (cn + NG - 1) / NG;
|
| int a0 = g * csz;
|
| if (a0 < si0) a0 = si0;
|
| const int a1 = ((g * csz) + csz < cn) ? (g * csz) + csz : cn;
|
| float acc = 0.f;
|
| for (int si = a0; si < a1; ++si)
|
| acc = fmaf(sc[si],
|
| bf2f(kv_staged ? vs_sh[(long long)si * D + d]
|
| : vc[(long long)(s0 + si) * D + d]),
|
| acc);
|
| pv[g * D + d] = acc;
|
| }
|
| __syncthreads();
|
| for (int d = threadIdx.x; d < D; d += blockDim.x) {
|
| float acc = 0.f;
|
| for (int g2 = 0; g2 < NG; ++g2) acc += pv[g2 * D + d];
|
| part[d] = acc;
|
| }
|
| } else {
|
| for (int d = threadIdx.x; d < D; d += blockDim.x) {
|
| float acc = 0.f;
|
| for (int si = si0; si < cn; ++si)
|
| acc = fmaf(sc[si],
|
| bf2f(kv_staged ? vs_sh[(long long)si * D + d]
|
| : vc[(long long)(s0 + si) * D + d]),
|
| acc);
|
| part[d] = acc;
|
| }
|
| }
|
| if (threadIdx.x == 0) {
|
| part[D] = s_m;
|
| part[D + 1] = lsum;
|
| }
|
| __syncthreads();
|
| }
|
| }
|
| }
|
|
|
|
|
|
|
|
|
| __device__ void ph_kv_append(const long long* P, int pos, int M) {
|
| const long long max_seq = P[7];
|
| const int qk_flag = ((int)P[8]) & 0xFFFF;
|
| const float eps = bits2f(P[9]);
|
| const float* invf = reinterpret_cast<const float*>(P[10]);
|
| const int Hq = (int)P[11], Hkv = ((int)P[12]) & 0xFFFF;
|
| const int D = (int)P[13];
|
| const int asbits = (int)(P[15] >> 32);
|
| const float ascale = (asbits != 0) ? __int_as_float(asbits) : 1.0f;
|
| const long long KT = (long long)(Hq + 2 * Hkv) * D;
|
| const bf16* knw = reinterpret_cast<const bf16*>(P[6]);
|
|
|
| __shared__ float s_red[32];
|
| __shared__ float s_inv;
|
| __shared__ float hbuf[MAX_HEAD_DIM];
|
|
|
| const int total = M * Hkv;
|
| for (int v = blockIdx.x; v < total; v += gridDim.x) {
|
| const int m = v / Hkv;
|
| const int kvh = v % Hkv;
|
| const int pm = pos + m;
|
| const bf16* qkv = reinterpret_cast<const bf16*>(P[1]) + (long long)m * KT;
|
| bf16* kc = reinterpret_cast<bf16*>(P[2]) + (long long)kvh * max_seq * D;
|
| bf16* vc = reinterpret_cast<bf16*>(P[3]) + (long long)kvh * max_seq * D;
|
| kv_norm_rope_append(qkv, kc, vc, knw, qk_flag, eps, invf, Hq, Hkv, kvh,
|
| D, pm, s_red, &s_inv, hbuf, ascale);
|
| }
|
| }
|
|
|
|
|
| __device__ void ph_normres(const long long* P) {
|
| if (blockIdx.x != 0) return;
|
| const bf16* t = reinterpret_cast<const bf16*>(P[1]);
|
| const bf16* w = reinterpret_cast<const bf16*>(P[2]);
|
| bf16* hid = reinterpret_cast<bf16*>(P[3]);
|
| const long long n = P[7];
|
| const float eps = bits2f(P[14]);
|
| const float lscale = bits2f(P[15]);
|
| __shared__ float s_red[32];
|
| __shared__ float s_inv;
|
| float ss = 0.f;
|
| for (long long k = threadIdx.x; k < n; k += blockDim.x) {
|
| const float v = bf2f(t[k]);
|
| ss += v * v;
|
| }
|
| ss = block_sum(ss, s_red);
|
| if (threadIdx.x == 0) s_inv = rsqrtf(ss / (float)n + eps);
|
| __syncthreads();
|
| for (long long k = threadIdx.x; k < n; k += blockDim.x) {
|
| const float nv = bf2f(f2bf((bf2f(t[k]) * s_inv) * bf2f(w[k])));
|
| float h = bf2f(f2bf(bf2f(hid[k]) + nv));
|
| if (lscale != 1.f) h = bf2f(f2bf(h * lscale));
|
| hid[k] = f2bf(h);
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
| __device__ void ph_plemix(const long long* P) {
|
| const bf16* ctx = reinterpret_cast<const bf16*>(P[1]);
|
| const bf16* w = reinterpret_cast<const bf16*>(P[2]);
|
| bf16* out = reinterpret_cast<bf16*>(P[3]);
|
| const bf16* tok = reinterpret_cast<const bf16*>(P[4]);
|
| const long long L = P[7], C = P[8];
|
| const float eps = bits2f(P[14]);
|
| const float pscale = bits2f(P[15]);
|
| __shared__ float s_red[32];
|
| __shared__ float s_inv;
|
| __shared__ float xbuf[512];
|
| for (long long l = blockIdx.x; l < L; l += gridDim.x) {
|
| float ss = 0.f;
|
| for (int j = threadIdx.x; j < (int)C; j += blockDim.x) {
|
| const float v = bf2f(f2bf(bf2f(ctx[l * C + j]) * pscale));
|
| xbuf[j] = v;
|
| ss += v * v;
|
| }
|
| ss = block_sum(ss, s_red);
|
| if (threadIdx.x == 0) s_inv = rsqrtf(ss / (float)C + eps);
|
| __syncthreads();
|
| for (int j = threadIdx.x; j < (int)C; j += blockDim.x) {
|
| const float nv = bf2f(f2bf((xbuf[j] * s_inv) * bf2f(w[j])));
|
| const float mixed = bf2f(f2bf(nv + bf2f(tok[l * C + j])));
|
| out[l * C + j] = f2bf(mixed * 0.70710678118654752440f);
|
| }
|
| __syncthreads();
|
| }
|
| }
|
|
|
| __device__ void ph_argmax_part(const long long* P, int M) {
|
| const float* lg = reinterpret_cast<const float*>(P[1]);
|
| unsigned long long* parts = reinterpret_cast<unsigned long long*>(P[3]);
|
| const long long V = P[7];
|
| __shared__ unsigned long long s64[32];
|
| for (int m = 0; m < M; ++m) {
|
| unsigned long long best = amax_key(-INFINITY, 0xFFFFFFFFu);
|
| for (long long i = (long long)blockIdx.x * blockDim.x + threadIdx.x;
|
| i < V; i += (long long)gridDim.x * blockDim.x) {
|
|
|
|
|
| const unsigned long long k =
|
| amax_key(bf2f(f2bf(lg[(long long)m * V + i])), (unsigned)i);
|
| best = (k > best) ? k : best;
|
| }
|
| best = block_max_u64(best, s64);
|
| if (threadIdx.x == 0)
|
| parts[(long long)m * gridDim.x + blockIdx.x] = best;
|
| if (m + 1 < M) __syncthreads();
|
| }
|
| }
|
|
|
|
|
|
|
| __device__ void ph_argmax_fin(const long long* P, int step_slot, int M) {
|
| if ((int)blockIdx.x >= M) return;
|
| const int m = (int)blockIdx.x;
|
| const unsigned long long* parts =
|
| reinterpret_cast<const unsigned long long*>(P[1]) +
|
| (long long)m * gridDim.x;
|
| int* tok = reinterpret_cast<int*>(P[3]);
|
| int* toks_out = reinterpret_cast<int*>(P[4]);
|
| const long long tstride = P[8];
|
| unsigned long long best = amax_key(-INFINITY, 0xFFFFFFFFu);
|
| for (int i = threadIdx.x; i < gridDim.x; i += blockDim.x) {
|
| const unsigned long long k = parts[i];
|
| best = (k > best) ? k : best;
|
| }
|
| __shared__ unsigned long long s64[32];
|
| best = block_max_u64(best, s64);
|
| if (threadIdx.x == 0) {
|
| const int idx = (int)(0xFFFFFFFFu - (unsigned)(best & 0xFFFFFFFFull));
|
| tok[m] = idx;
|
| if (toks_out != nullptr && step_slot >= 0)
|
| toks_out[(long long)m * tstride + step_slot] = idx;
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| __device__ void ph_normb(const long long* P, int M) {
|
| const int m = blockIdx.x;
|
| if (m >= M) return;
|
| const long long K = P[8];
|
| const bf16* xin = reinterpret_cast<const bf16*>(P[1]) + (long long)m * K;
|
| const bf16* gamma = reinterpret_cast<const bf16*>(P[2]);
|
| bf16* xg = reinterpret_cast<bf16*>(P[3]) + (long long)m * K;
|
| const int variant = (int)P[9] & ITF_BASE_MASK;
|
| const float eps = bits2f(P[14]);
|
| __shared__ float s_red[32];
|
| __shared__ float s_scale;
|
| const long long G = K / 8;
|
| float ss = 0.f;
|
| for (long long g = threadIdx.x; g < G; g += blockDim.x) {
|
| const int4 x4 = *reinterpret_cast<const int4*>(xin + g * 8);
|
| const __nv_bfloat162* xp =
|
| reinterpret_cast<const __nv_bfloat162*>(&x4);
|
| #pragma unroll
|
| for (int j = 0; j < 4; ++j) {
|
| const float lo = __low2float(xp[j]);
|
| const float hi = __high2float(xp[j]);
|
| ss += lo * lo;
|
| ss += hi * hi;
|
| }
|
| }
|
| ss = block_sum(ss, s_red);
|
| if (threadIdx.x == 0) s_scale = rsqrtf(ss / (float)K + eps);
|
| __syncthreads();
|
| const float inv = s_scale;
|
| for (long long g = threadIdx.x; g < G; g += blockDim.x) {
|
| const int4 x4 = *reinterpret_cast<const int4*>(xin + g * 8);
|
| const int4 g4 = *reinterpret_cast<const int4*>(gamma + g * 8);
|
| const __nv_bfloat162* xp = reinterpret_cast<const __nv_bfloat162*>(&x4);
|
| const __nv_bfloat162* gp = reinterpret_cast<const __nv_bfloat162*>(&g4);
|
| int4 o4;
|
| __nv_bfloat162* op = reinterpret_cast<__nv_bfloat162*>(&o4);
|
| #pragma unroll
|
| for (int j = 0; j < 4; ++j) {
|
| if (variant == IT_RMSNORM_G) {
|
| op[j].x = f2bf((__low2float(xp[j]) * inv) * __low2float(gp[j]));
|
| op[j].y = f2bf((__high2float(xp[j]) * inv) * __high2float(gp[j]));
|
| } else {
|
| op[j].x = f2bf(__low2float(gp[j]) *
|
| bf2f(f2bf(__low2float(xp[j]) * inv)));
|
| op[j].y = f2bf(__high2float(gp[j]) *
|
| bf2f(f2bf(__high2float(xp[j]) * inv)));
|
| }
|
| }
|
| *reinterpret_cast<int4*>(xg + g * 8) = o4;
|
| }
|
| }
|
|
|
|
|
| __device__ void ph_glub(const long long* P, int M) {
|
| const long long K = P[8];
|
| const bf16* xin = reinterpret_cast<const bf16*>(P[1]);
|
| bf16* xg = reinterpret_cast<bf16*>(P[3]);
|
| const int variant = (int)P[9] & ITF_BASE_MASK;
|
| const long long tot = (long long)M * K;
|
| for (long long i = (long long)blockIdx.x * blockDim.x + threadIdx.x;
|
| i < tot; i += (long long)gridDim.x * blockDim.x) {
|
| const int m = (int)(i / K);
|
| const long long k = i % K;
|
| const bf16* gate = xin + (long long)m * 2 * K;
|
| const float g = bf2f(gate[k]);
|
| const float up = bf2f(gate[K + k]);
|
| if (variant == IT_GELU_GLU) {
|
| const float act = bf2f(f2bf(gelu_tanh_f(g)));
|
| xg[i] = f2bf(act * up);
|
| } else {
|
| const float sig = 1.f / (1.f + expf(-g));
|
| const float sg = bf2f(f2bf(g * sig));
|
| xg[i] = f2bf(sg * up);
|
| }
|
| }
|
| }
|
|
|
|
|
| __device__ void ph_attnfinb(const long long* P, int M, const int* pos_b,
|
| int step) {
|
| const long long K = P[8];
|
| const float* part = reinterpret_cast<const float*>(P[1]);
|
| bf16* xg = reinterpret_cast<bf16*>(P[3]);
|
| const int Hq = (int)P[11];
|
| const int D = (int)P[13];
|
| const int chbits = (int)(P[12] >> 16) & 0xFFFF;
|
| const int CH = (chbits > 0 && chbits <= ATTN_CHUNK) ? chbits : ATTN_CHUNK;
|
| const int maxch = (int)(P[15] & 0xFFFF);
|
| const int fin_win = (int)((P[15] >> 16) & 0xFFFF);
|
| const long long tot = (long long)M * K;
|
| for (long long i = (long long)blockIdx.x * blockDim.x + threadIdx.x;
|
| i < tot; i += (long long)gridDim.x * blockDim.x) {
|
| const int m = (int)(i / K);
|
| const long long k = i % K;
|
| const int pm = pm_of(0, m, pos_b, step);
|
| const int nch = (pm + CH) / CH;
|
| const int s_lo = (fin_win > 0 && pm + 1 > fin_win) ? pm + 1 - fin_win : 0;
|
| const int nch_lo = s_lo / CH;
|
| const float* mpart =
|
| part + (long long)m * ((long long)Hq * maxch * (D + 2));
|
| xg[i] = f2bf(attn_finalize(mpart, (int)(k / D), (int)(k % D), D, maxch,
|
| nch, nch_lo));
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
| template <int NB>
|
| __device__ void ph_gemv_plain(const long long* P, int M, int rs) {
|
| const bf16* W = reinterpret_cast<const bf16*>(P[2]);
|
| const bf16* resid = reinterpret_cast<const bf16*>(P[5]);
|
| const bf16* xin = reinterpret_cast<const bf16*>(P[1]);
|
| const long long N = P[7], K = P[8];
|
| const bool tiled = ((P[9] >> 20) & 1) != 0;
|
| const int epi = (int)P[10];
|
|
|
| extern __shared__ unsigned char smem_raw[];
|
| int4* rng = reinterpret_cast<int4*>(smem_raw);
|
| const int lane = threadIdx.x & 31, wib = threadIdx.x >> 5;
|
| const long long gwarp =
|
| ((long long)blockIdx.x * blockDim.x + threadIdx.x) >> 5;
|
| const long long nwarps = ((long long)gridDim.x * blockDim.x) >> 5;
|
| const int rmask = rs - 1;
|
| int4* ringw = rng + (wib * rs) * 32 + lane;
|
| const long long kbase = (long long)lane * 8;
|
| const long long ntiles = (kbase < K) ? (K - kbase + 255) / 256 : 0;
|
| const long long K8 = K >> 3;
|
| long long irow = gwarp, itile = 0, ig = 0, cg = 0;
|
| auto issue_one = [&]() {
|
| if (irow < N && ntiles > 0) {
|
| const bf16* src =
|
| tiled ? W + (((irow >> 3) * K8 + (kbase >> 3) + itile * 32) << 6) +
|
| ((irow & 7) << 3)
|
| : W + irow * K + kbase + itile * 256;
|
| __pipeline_memcpy_async(ringw + ((int)ig & rmask) * 32, src, 16);
|
| __pipeline_commit();
|
| ++ig;
|
| if (++itile == ntiles) {
|
| itile = 0;
|
| irow += nwarps;
|
| }
|
| }
|
| };
|
| for (int i = 0; i < rs; ++i) issue_one();
|
|
|
| for (long long row = gwarp; row < N; row += nwarps) {
|
| float acc[NB];
|
| #pragma unroll
|
| for (int m = 0; m < NB; ++m) acc[m] = 0.f;
|
| for (long long t = 0; t < ntiles; ++t) {
|
| __pipeline_wait_prior((int)(ig - cg - 1));
|
| const int4 w4 = ringw[((int)cg & rmask) * 32];
|
| ++cg;
|
| issue_one();
|
| const long long k = kbase + t * 256;
|
| const __nv_bfloat162* wp = reinterpret_cast<const __nv_bfloat162*>(&w4);
|
| #pragma unroll
|
| for (int m = 0; m < NB; ++m) {
|
| if (m < M) {
|
| const __nv_bfloat162* xp =
|
| reinterpret_cast<const __nv_bfloat162*>(xin +
|
| (long long)m * K + k);
|
| #pragma unroll
|
| for (int j = 0; j < 4; ++j) {
|
| acc[m] = fmaf(__low2float(wp[j]), __low2float(xp[j]), acc[m]);
|
| acc[m] = fmaf(__high2float(wp[j]), __high2float(xp[j]), acc[m]);
|
| }
|
| }
|
| }
|
| }
|
| #pragma unroll
|
| for (int m = 0; m < NB; ++m) {
|
| if (m < M) {
|
| const float a = warp_sum(acc[m]);
|
| if (lane == 0) gemv_store(P, epi, N, resid, m, row, a);
|
| }
|
| }
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| template <int NB>
|
| __device__ void ph_gemv_q4(const long long* P, int M) {
|
| const unsigned char* W = reinterpret_cast<const unsigned char*>(P[2]);
|
| const float* absmax = reinterpret_cast<const float*>(P[6]);
|
| const bf16* resid = reinterpret_cast<const bf16*>(P[5]);
|
| const bf16* xin = reinterpret_cast<const bf16*>(P[1]);
|
| const long long N = P[7], K = P[8];
|
| const int epi = (int)P[10];
|
| const int lane = threadIdx.x & 31;
|
| const long long gwarp =
|
| ((long long)blockIdx.x * blockDim.x + threadIdx.x) >> 5;
|
| const long long nwarps = ((long long)gridDim.x * blockDim.x) >> 5;
|
| const long long kbase = (long long)lane * 8;
|
| const long long ntiles = (kbase < K) ? (K - kbase + 255) / 256 : 0;
|
| const long long Kh = K >> 1;
|
|
|
| for (long long row = gwarp; row < N; row += nwarps) {
|
| float acc[NB];
|
| #pragma unroll
|
| for (int m = 0; m < NB; ++m) acc[m] = 0.f;
|
| for (long long t = 0; t < ntiles; ++t) {
|
| const long long k = kbase + t * 256;
|
| const unsigned int pw =
|
| *reinterpret_cast<const unsigned int*>(W + row * Kh + (k >> 1));
|
| const float am = absmax[(row * K + k) >> 6];
|
| float w8[8];
|
| #pragma unroll
|
| for (int b = 0; b < 4; ++b) {
|
| const unsigned int by = (pw >> (b * 8)) & 0xFFu;
|
|
|
| w8[2 * b] = bf2f(f2bf(NF4_CODE[by >> 4] * am));
|
| w8[2 * b + 1] = bf2f(f2bf(NF4_CODE[by & 0xF] * am));
|
| }
|
| #pragma unroll
|
| for (int m = 0; m < NB; ++m) {
|
| if (m < M) {
|
| const bf16* xp = xin + (long long)m * K + k;
|
| #pragma unroll
|
| for (int j = 0; j < 8; ++j)
|
| acc[m] = fmaf(w8[j], bf2f(xp[j]), acc[m]);
|
| }
|
| }
|
| }
|
| #pragma unroll
|
| for (int m = 0; m < NB; ++m) {
|
| if (m < M) {
|
| const float a = warp_sum(acc[m]);
|
| if (lane == 0) gemv_store(P, epi, N, resid, m, row, a);
|
| }
|
| }
|
| }
|
| }
|
|
|
| template <int NB>
|
| __device__ __forceinline__ void dispatch_phase(const long long* P, int pos,
|
| int M, int step_slot,
|
| int prompt_len,
|
| int ring_stages,
|
| const int* pos_b, int step,
|
| long long kv_bstride) {
|
| switch ((int)P[0]) {
|
| case OP_EMBED: ph_embed(P, pos, M, prompt_len, step_slot, pos_b); break;
|
| case OP_GEMV: ph_gemv<NB>(P, pos, M, ring_stages, pos_b, step); break;
|
| case OP_ATTN: ph_attn(P, pos, M, pos_b, step, kv_bstride); break;
|
| case OP_ARGMAX_PART: ph_argmax_part(P, M); break;
|
| case OP_ARGMAX_FIN: ph_argmax_fin(P, step_slot, M); break;
|
| case OP_KV_APPEND: ph_kv_append(P, pos, M); break;
|
| case OP_NORMRES: ph_normres(P); break;
|
| case OP_PLEMIX: ph_plemix(P); break;
|
| case OP_GEMV_PLAIN: ph_gemv_plain<NB>(P, M, ring_stages); break;
|
| case OP_GEMV_Q4: ph_gemv_q4<NB>(P, M); break;
|
| case OP_NORMB: ph_normb(P, M); break;
|
| case OP_GLUB: ph_glub(P, M); break;
|
| case OP_ATTNFINB: ph_attnfinb(P, M, pos_b, step); break;
|
| default: break;
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| #define BAR_STRIPES 32
|
|
|
| __device__ void grid_barrier(int* bar, int* local_sense) {
|
| __syncthreads();
|
| if (threadIdx.x == 0) {
|
| const int ls = *local_sense ^ 1;
|
| *local_sense = ls;
|
| __threadfence();
|
|
|
|
|
|
|
| const int nb = (int)gridDim.x;
|
| const int stripe = (int)blockIdx.x & (BAR_STRIPES - 1);
|
| const int in_stripe =
|
| nb / BAR_STRIPES + ((stripe < (nb % BAR_STRIPES)) ? 1 : 0);
|
| int* sense = bar + BAR_STRIPES + 1;
|
| if (atomicAdd(bar + stripe, 1) == in_stripe - 1) {
|
| atomicExch(bar + stripe, 0);
|
| __threadfence();
|
| const int nstripes = (nb < BAR_STRIPES) ? nb : BAR_STRIPES;
|
| if (atomicAdd(bar + BAR_STRIPES, 1) == nstripes - 1) {
|
| atomicExch(bar + BAR_STRIPES, 0);
|
| __threadfence();
|
| atomicExch(sense, ls);
|
| } else {
|
| const volatile int* vs = sense;
|
| while (*vs != ls) {
|
| }
|
| }
|
| } else {
|
| const volatile int* vs = sense;
|
| while (*vs != ls) {
|
| }
|
| }
|
| __threadfence();
|
| }
|
| __syncthreads();
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| template <int NB>
|
| __global__ void __launch_bounds__(BLOCK_THREADS, 2)
|
| mega_kernel(const long long* __restrict__ prog, int n_phases,
|
| int pos0, int total, int slot0, int prompt_len,
|
| int chunk_m, int ring_stages, int* bar,
|
| long long* __restrict__ ts,
|
| const int* __restrict__ pos_b, int B,
|
| long long kv_bstride) {
|
| __shared__ int s_sense;
|
| if (threadIdx.x == 0) s_sense = atomicAdd(bar + BAR_STRIPES + 1, 0);
|
| __syncthreads();
|
|
|
|
|
| if (ts != nullptr && blockIdx.x == 0 && threadIdx.x == 0)
|
| ts[0] = (long long)clock64();
|
| const bool batch = (pos_b != nullptr);
|
| int pos = pos0;
|
| const int pos_end = pos0 + total;
|
| while (pos < pos_end) {
|
| int M = 1;
|
| if (batch) {
|
| M = B;
|
| } else if (pos < prompt_len) {
|
| M = prompt_len - pos;
|
| if (M > chunk_m) M = chunk_m;
|
| if (pos + M > pos_end) M = pos_end - pos;
|
| }
|
| const int step = pos - pos0;
|
| const int slot = batch ? (slot0 + step) : (slot0 + (pos + M - 1 - pos0));
|
| const bool final_step = batch ? (pos + 1 >= pos_end)
|
| : (pos + M >= pos_end);
|
| for (int p = 0; p < n_phases; ++p) {
|
| const long long* P = prog + (long long)p * 16;
|
| const int op = (int)P[0];
|
| if (op == OP_KV_APPEND && (M == 1 || batch)) continue;
|
| if (op == OP_ARGMAX_FIN && !final_step && !batch)
|
| continue;
|
| dispatch_phase<NB>(P, pos, M, slot, batch ? -1 : prompt_len,
|
| ring_stages, pos_b, step, kv_bstride);
|
| if (!(final_step && p + 1 == n_phases)) {
|
|
|
|
|
|
|
| for (int q = p + 1; q < n_phases; ++q) {
|
| const long long* Pn = prog + (long long)q * 16;
|
| const int opn = (int)Pn[0];
|
| if (opn == OP_KV_APPEND && (M == 1 || batch)) continue;
|
| if (opn == OP_GEMV || opn == OP_GEMV_PLAIN) {
|
| const long long w =
|
| ((long long)blockIdx.x * blockDim.x + threadIdx.x) >> 5;
|
| const long long kb = (long long)(threadIdx.x & 31) * 8;
|
| if (w < Pn[7] && kb < Pn[8]) {
|
| const long long off =
|
| ((Pn[9] >> 20) & 1)
|
| ? (((w >> 3) * (Pn[8] >> 3) + (kb >> 3)) << 6) +
|
| ((w & 7) << 3)
|
| : w * Pn[8] + kb;
|
| const char* wr =
|
| reinterpret_cast<const char*>(Pn[2]) + off * 2;
|
| asm volatile("prefetch.global.L2 [%0];" ::"l"(wr));
|
| asm volatile("prefetch.global.L2 [%0];" ::"l"(wr + 512));
|
| }
|
| }
|
| break;
|
| }
|
| grid_barrier(bar, &s_sense);
|
| }
|
| if (ts != nullptr && pos == pos0 && blockIdx.x == 0 &&
|
| threadIdx.x == 0)
|
| ts[p + 1] = (long long)clock64();
|
| }
|
| pos += batch ? 1 : M;
|
| }
|
| }
|
|
|
| __global__ void __launch_bounds__(BLOCK_THREADS, 2)
|
| phase_kernel(const long long* __restrict__ prog, int p,
|
| int pos, int step_slot, int prompt_len,
|
| int ring_stages) {
|
| const long long* P = prog + (long long)p * 16;
|
| if ((int)P[0] == OP_KV_APPEND) return;
|
| dispatch_phase<8>(P, pos, 1, step_slot, -1, ring_stages, nullptr, 0, 0);
|
| }
|
|
|
|
|
|
|
| #define MAK_MAXB_BIG 16
|
|
|
| }
|
|
|
| #include <stdlib.h>
|
|
|
|
|
|
|
|
|
|
|
| int mak_ring_stages_impl(int stage_bytes) {
|
| static int cached_dev = -1;
|
| static int cached_stage = -1;
|
| static int cached_rs = -1;
|
| int dev = 0;
|
| cudaGetDevice(&dev);
|
| if (dev != cached_dev || stage_bytes != cached_stage || cached_rs < 0) {
|
| int shm_sm = 0, optin = 0;
|
| cudaDeviceGetAttribute(&shm_sm, cudaDevAttrMaxSharedMemoryPerMultiprocessor,
|
| dev);
|
| cudaDeviceGetAttribute(&optin, cudaDevAttrMaxSharedMemoryPerBlockOptin,
|
| dev);
|
| cudaFuncAttributes fa{};
|
| cudaFuncGetAttributes(&fa, mak::mega_kernel<8>);
|
| const int stat = (int)fa.sharedSizeBytes;
|
| long long by_occ = ((long long)shm_sm / 2 - stat - stage_bytes) /
|
| GEMV_RING_STAGE_BYTES;
|
| long long by_win = ((long long)optin - stat - stage_bytes) /
|
| GEMV_RING_STAGE_BYTES;
|
| if (by_occ < 4) by_occ = 4;
|
| long long rs = (by_occ < by_win) ? by_occ : by_win;
|
| if (rs > 4) rs = 4;
|
| if (rs < 1) rs = 1;
|
| while (rs & (rs - 1)) rs &= rs - 1;
|
| const char* env = getenv("MAK_RING");
|
| if (env != nullptr) {
|
| long long r = atoll(env);
|
| if (r >= 1 && r <= 16 && !(r & (r - 1)) &&
|
| (long long)stat + stage_bytes + r * GEMV_RING_STAGE_BYTES <= optin)
|
| rs = r;
|
| }
|
| cached_rs = (int)rs;
|
| cached_dev = dev;
|
| cached_stage = stage_bytes;
|
| }
|
| return cached_rs;
|
| }
|
|
|
| int mak_grid_blocks_impl(int smem_bytes) {
|
| static int cached_dev = -1;
|
| static int cached_smem = -1;
|
| static int cached_grid = -1;
|
| int dev = 0;
|
| cudaGetDevice(&dev);
|
| if (dev != cached_dev || smem_bytes != cached_smem || cached_grid < 0) {
|
| cudaDeviceProp prop;
|
| cudaGetDeviceProperties(&prop, dev);
|
|
|
|
|
|
|
| int optin = 0;
|
| cudaDeviceGetAttribute(&optin, cudaDevAttrMaxSharedMemoryPerBlockOptin,
|
| dev);
|
| cudaFuncAttributes fa{};
|
| cudaFuncGetAttributes(&fa, mak::mega_kernel<8>);
|
| cudaFuncSetAttribute(mak::mega_kernel<8>,
|
| cudaFuncAttributeMaxDynamicSharedMemorySize,
|
| optin - (int)fa.sharedSizeBytes);
|
| cudaFuncGetAttributes(&fa, mak::mega_kernel<MAK_MAXB_BIG>);
|
| cudaFuncSetAttribute(mak::mega_kernel<MAK_MAXB_BIG>,
|
| cudaFuncAttributeMaxDynamicSharedMemorySize,
|
| optin - (int)fa.sharedSizeBytes);
|
| cudaFuncGetAttributes(&fa, mak::phase_kernel);
|
| cudaFuncSetAttribute(mak::phase_kernel,
|
| cudaFuncAttributeMaxDynamicSharedMemorySize,
|
| optin - (int)fa.sharedSizeBytes);
|
| cudaGetLastError();
|
| int nb = 0;
|
| cudaOccupancyMaxActiveBlocksPerMultiprocessor(&nb, mak::mega_kernel<8>,
|
| BLOCK_THREADS, smem_bytes);
|
| if (nb < 1) nb = 1;
|
| int grid = nb * prop.multiProcessorCount;
|
| const char* env = getenv("MAK_GRID");
|
| if (env != nullptr) {
|
| const int g = atoi(env);
|
| if (g > 0 && g <= grid) grid = g;
|
| }
|
| cached_grid = grid;
|
| cached_dev = dev;
|
| cached_smem = smem_bytes;
|
| }
|
| return cached_grid;
|
| }
|
|
|
|
|
|
|
|
|
| int mak_grid_blocks_big_impl(int smem_bytes) {
|
| static int cached_dev = -1;
|
| static int cached_smem = -1;
|
| static int cached_grid = -1;
|
| int dev = 0;
|
| cudaGetDevice(&dev);
|
| if (dev != cached_dev || smem_bytes != cached_smem || cached_grid < 0) {
|
| cudaDeviceProp prop;
|
| cudaGetDeviceProperties(&prop, dev);
|
| int nb = 0;
|
| cudaOccupancyMaxActiveBlocksPerMultiprocessor(
|
| &nb, mak::mega_kernel<MAK_MAXB_BIG>, BLOCK_THREADS, smem_bytes);
|
| if (nb < 1) nb = 1;
|
| int grid = nb * prop.multiProcessorCount;
|
| const char* env = getenv("MAK_GRID");
|
| if (env != nullptr) {
|
| const int g = atoi(env);
|
| if (g > 0 && g <= grid) grid = g;
|
| }
|
| cached_grid = grid;
|
| cached_dev = dev;
|
| cached_smem = smem_bytes;
|
| }
|
| return cached_grid;
|
| }
|
|
|
| int mak_batch_maxb_impl() { return MAK_MAXB_BIG; }
|
|
|
| cudaError_t mak_launch_mega(const long long* prog, int n_phases, int pos0,
|
| int total, int slot0, int prompt_len,
|
| int chunk_m, int ring_stages, int* bar, int grid,
|
| int smem_bytes, cudaStream_t stream,
|
| long long* ts) {
|
| mak::mega_kernel<8><<<grid, BLOCK_THREADS, smem_bytes, stream>>>(
|
| prog, n_phases, pos0, total, slot0, prompt_len, chunk_m, ring_stages,
|
| bar, ts, nullptr, 1, 0);
|
| return cudaGetLastError();
|
| }
|
|
|
| cudaError_t mak_launch_mega_batch(const long long* prog, int n_phases,
|
| int steps, int slot0, int ring_stages,
|
| int* bar, int grid, int smem_bytes,
|
| const int* pos_b, int B,
|
| long long kv_bstride,
|
| cudaStream_t stream) {
|
| mak::mega_kernel<8><<<grid, BLOCK_THREADS, smem_bytes, stream>>>(
|
| prog, n_phases, 0, steps, slot0, -1, 1, ring_stages, bar, nullptr,
|
| pos_b, B, kv_bstride);
|
| return cudaGetLastError();
|
| }
|
|
|
| cudaError_t mak_launch_mega_batch_big(const long long* prog, int n_phases,
|
| int steps, int slot0, int ring_stages,
|
| int* bar, int grid, int smem_bytes,
|
| const int* pos_b, int B,
|
| long long kv_bstride,
|
| cudaStream_t stream) {
|
| mak::mega_kernel<MAK_MAXB_BIG><<<grid, BLOCK_THREADS, smem_bytes, stream>>>(
|
| prog, n_phases, 0, steps, slot0, -1, 1, ring_stages, bar, nullptr,
|
| pos_b, B, kv_bstride);
|
| return cudaGetLastError();
|
| }
|
|
|
| cudaError_t mak_launch_phase(const long long* prog, int phase, int pos,
|
| int step_slot, int ring_stages, int grid,
|
| int smem_bytes, cudaStream_t stream) {
|
| mak::phase_kernel<<<grid, BLOCK_THREADS, smem_bytes, stream>>>(
|
| prog, phase, pos, step_slot, 0, ring_stages);
|
| return cudaGetLastError();
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|