call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cpp_src = r\"\"\"\n#include <torch/extension.h>\n\ntorch::Tensor tri_forward(torch::Tensor pair_repr, torch::Tensor pair_mask,\n torch::Tensor ln_w, torch::Tensor ln_b,\n torch::Tensor q_w, torch::Tensor k_w, torch::Tensor v_w,\n torch::Tensor gate_w, torch::Tensor gate_b,\n torch::Tensor bias_w,\n torch::Tensor out_w, torch::Tensor out_b,\n int64_t num_heads);\n\"\"\"\n\n_cuda_src = r\"\"\"\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math_constants.h>\n\n#ifndef MAX_D\n#define MAX_D 128\n#endif\n#ifndef MAX_N\n#define MAX_N 64\n#endif\n\n__device__ __forceinline__ float warp_safe_exp(float x) { return expf(x); }\n\n__global__ void norm_proj_kernel(const float* __restrict__ inp,\n const float* __restrict__ ln_w,\n const float* __restrict__ ln_b,\n const float* __restrict__ q_w,\n const float* __restrict__ k_w,\n const float* __restrict__ v_w,\n const float* __restrict__ gate_w,\n const float* __restrict__ gate_b,\n const float* __restrict__ bias_w,\n float* __restrict__ q,\n float* __restrict__ k,\n float* __restrict__ v,\n float* __restrict__ gate,\n float* __restrict__ bias,\n int B, int N, int D, int H) {\n int token = blockIdx.x;\n int tid = threadIdx.x;\n int total_tokens = B * N * N;\n if (token >= total_tokens) return;\n\n __shared__ float red[256];\n __shared__ float x[MAX_D];\n\n const float* base = inp + (long long)token * D;\n float s = 0.f;\n for (int c = tid; c < D; c += blockDim.x) s += base[c];\n red[tid] = s;\n __syncthreads();\n for (int stride = blockDim.x >> 1; stride > 0; stride >>= 1) {\n if (tid < stride) red[tid] += red[tid + stride];\n __syncthreads();\n }\n float mean = red[0] / (float)D;\n\n s = 0.f;\n for (int c = tid; c < D; c += blockDim.x) {\n float d = base[c] - mean;\n s += d * d;\n }\n red[tid] = s;\n __syncthreads();\n for (int stride = blockDim.x >> 1; stride > 0; stride >>= 1) {\n if (tid < stride) red[tid] += red[tid + stride];\n __syncthreads();\n }\n float invstd = rsqrtf(red[0] / (float)D + 1.0e-5f);\n\n for (int c = tid; c < D; c += blockDim.x) {\n x[c] = (base[c] - mean) * invstd * ln_w[c] + ln_b[c];\n }\n __syncthreads();\n\n int total_out = 4 * D + H;\n for (int o = tid; o < total_out; o += blockDim.x) {\n const float* wptr;\n int row;\n int kind;\n if (o < D) { kind = 0; row = o; wptr = q_w + (long long)row * D; }\n else if (o < 2 * D) { kind = 1; row = o - D; wptr = k_w + (long long)row * D; }\n else if (o < 3 * D) { kind = 2; row = o - 2 * D; wptr = v_w + (long long)row * D; }\n else if (o < 4 * D) { kind = 3; row = o - 3 * D; wptr = gate_w + (long long)row * D; }\n else { kind = 4; row = o - 4 * D; wptr = bias_w + (long long)row * D; }\n float acc = 0.f;\n #pragma unroll\n for (int c = 0; c < MAX_D; ++c) {\n if (c < D) acc = fmaf(x[c], wptr[c], acc);\n }\n if (kind == 0) q[(long long)token * D + row] = acc;\n else if (kind == 1) k[(long long)token * D + row] = acc;\n else if (kind == 2) v[(long long)token * D + row] = acc;\n else if (kind == 3) {\n acc += gate_b[row];\n gate[(long long)token * D + row] = 1.f / (1.f + expf(-acc));\n } else {\n int j = token % N;\n int tmp = token / N;\n int i = tmp % N;\n int b = tmp / N;\n bias[((long long)b * H + row) * N * N + i * N + j] = acc;\n }\n }\n}\n\n__global__ void attention_kernel(const float* __restrict__ q,\n const float* __restrict__ k,\n const float* __restrict__ v,\n const float* __restrict__ gate,\n const float* __restrict__ bias,\n const float* __restrict__ mask,\n float* __restrict__ mid,\n int B, int N, int D, int H, int Hd) {\n int idx = blockIdx.x;\n int tid = threadIdx.x;\n int h = idx % H;\n int t = idx / H;\n int j = t % N;\n t /= N;\n int row = t % N;\n int b = t / N;\n\n __shared__ float scores[MAX_N];\n __shared__ float red[64];\n\n long long qtok = ((long long)b * N + row) * N + j;\n float scale = rsqrtf((float)Hd);\n\n for (int kk = tid; kk < N; kk += blockDim.x) {\n long long ktok = ((long long)b * N + row) * N + kk;\n float dot = 0.f;\n #pragma unroll\n for (int dd = 0; dd < 32; ++dd) {\n if (dd < Hd) dot = fmaf(q[qtok * D + h * Hd + dd], k[ktok * D + h * Hd + dd], dot);\n }\n float m = mask[((long long)b * N + j) * N + kk];\n float sc = dot * scale + bias[((long long)b * H + h) * N * N + j * N + kk];\n scores[kk] = (m == 0.f) ? -CUDART_INF_F : sc;\n }\n __syncthreads();\n\n float lmax = -CUDART_INF_F;\n for (int kk = tid; kk < N; kk += blockDim.x) lmax = fmaxf(lmax, scores[kk]);\n red[tid] = lmax;\n __syncthreads();\n for (int stride = blockDim.x >> 1; stride > 0; stride >>= 1) {\n if (tid < stride) red[tid] = fmaxf(red[tid], red[tid + stride]);\n __syncthreads();\n }\n float mx = red[0];\n\n float lsum = 0.f;\n for (int kk = tid; kk < N; kk += blockDim.x) {\n float e = expf(scores[kk] - mx);\n scores[kk] = e;\n lsum += e;\n }\n red[tid] = lsum;\n __syncthreads();\n for (int stride = blockDim.x >> 1; stride > 0; stride >>= 1) {\n if (tid < stride) red[tid] += red[tid + stride];\n __syncthreads();\n }\n float invsum = 1.f / red[0];\n for (int kk = tid; kk < N; kk += blockDim.x) scores[kk] *= invsum;\n __syncthreads();\n\n for (int dd = tid; dd < Hd; dd += blockDim.x) {\n float acc = 0.f;\n for (int kk = 0; kk < N; ++kk) {\n long long ktok = ((long long)b * N + row) * N + kk;\n acc = fmaf(scores[kk], v[ktok * D + h * Hd + dd], acc);\n }\n int dim = h * Hd + dd;\n mid[qtok * D + dim] = acc * gate[qtok * D + dim];\n }\n}\n\n__global__ void out_proj_kernel(const float* __restrict__ mid,\n const float* __restrict__ out_w,\n const float* __restrict__ out_b,\n float* __restrict__ out,\n int total_tokens, int D) {\n int token = blockIdx.x;\n int tid = threadIdx.x;\n if (token >= total_tokens) return;\n for (int oc = tid; oc < D; oc += blockDim.x) {\n const float* w = out_w + (long long)oc * D;\n const float* x = mid + (long long)token * D;\n float acc = out_b[oc];\n #pragma unroll\n for (int c = 0; c < MAX_D; ++c) {\n if (c < D) acc = fmaf(x[c], w[c], acc);\n }\n out[(long long)token * D + oc] = acc;\n }\n}\n\ntorch::Tensor tri_forward(torch::Tensor pair_repr, torch::Tensor pair_mask,\n torch::Tensor ln_w, torch::Tensor ln_b,\n torch::Tensor q_w, torch::Tensor k_w, torch::Tensor v_w,\n torch::Tensor gate_w, torch::Tensor gate_b,\n torch::Tensor bias_w,\n torch::Tensor out_w, torch::Tensor out_b,\n int64_t num_heads) {\n int B = (int)pair_repr.size(0);\n int N = (int)pair_repr.size(1);\n int D = (int)pair_repr.size(3);\n int H = (int)num_heads;\n int Hd = D / H;\n auto opts = pair_repr.options();\n auto q = torch::empty({B, N, N, D}, opts);\n auto k = torch::empty({B, N, N, D}, opts);\n auto v = torch::empty({B, N, N, D}, opts);\n auto gate = torch::empty({B, N, N, D}, opts);\n auto bias = torch::empty({B, H, N, N}, opts);\n auto mid = torch::empty({B, N, N, D}, opts);\n auto out = torch::empty({B, N, N, D}, opts);\n\n int total_tokens = B * N * N;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n norm_proj_kernel<<<total_tokens, 256, 0, stream>>>(\n pair_repr.data_ptr<float>(), ln_w.data_ptr<float>(), ln_b.data_ptr<float>(),\n q_w.data_ptr<float>(), k_w.data_ptr<float>(), v_w.data_ptr<float>(),\n gate_w.data_ptr<float>(), gate_b.data_ptr<float>(), bias_w.data_ptr<float>(),\n q.data_ptr<float>(), k.data_ptr<float>(), v.data_ptr<float>(), gate.data_ptr<float>(), bias.data_ptr<float>(),\n B, N, D, H);\n\n attention_kernel<<<total_tokens * H, 64, 0, stream>>>(\n q.data_ptr<float>(), k.data_ptr<float>(), v.data_ptr<float>(), gate.data_ptr<float>(),\n bias.data_ptr<float>(), pair_mask.data_ptr<float>(), mid.data_ptr<float>(),\n B, N, D, H, Hd);\n\n out_proj_kernel<<<total_tokens, 128, 0, stream>>>(\n mid.data_ptr<float>(), out_w.data_ptr<float>(), out_b.data_ptr<float>(), out.data_ptr<float>(),\n total_tokens, D);\n return out;\n}\n\"\"\"\n\n_ext = load_inline(\n name=\"tri_start_attn_ext_v1\",\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=[\"tri_forward\"],\n extra_cuda_cflags=[\"-O3\"],\n extra_cflags=[\"-O3\"],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, pair_dim, num_heads, dropout=0.0):\n super().__init__()\n self.num_heads = num_heads\n self.head_dim = pair_dim // num_heads\n assert pair_dim % num_heads == 0\n self.layer_norm = nn.LayerNorm(pair_dim)\n self.query = nn.Linear(pair_dim, pair_dim, bias=False)\n self.key = nn.Linear(pair_dim, pair_dim, bias=False)\n self.value = nn.Linear(pair_dim, pair_dim, bias=False)\n self.gate = nn.Linear(pair_dim, pair_dim)\n self.bias_proj = nn.Linear(pair_dim, num_heads, bias=False)\n self.out_proj = nn.Linear(pair_dim, pair_dim)\n self.dropout = nn.Dropout(dropout)\n\n def forward(self, pair_repr: torch.Tensor, pair_mask: torch.Tensor) -> torch.Tensor:\n return _ext.tri_forward(pair_repr, pair_mask,\n self.layer_norm.weight, self.layer_norm.bias,\n self.query.weight, self.key.weight, self.value.weight,\n self.gate.weight, self.gate.bias,\n self.bias_proj.weight,\n self.out_proj.weight, self.out_proj.bias,\n int(self.num_heads))\n"
}