call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import math\nimport torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n\n_cpp_src = r'''\n#include <torch/extension.h>\n\ntorch::Tensor forward_cuda(torch::Tensor msa_repr,\n torch::Tensor msa_mask,\n torch::Tensor ln_w,\n torch::Tensor ln_b,\n torch::Tensor q_w,\n torch::Tensor k_w,\n torch::Tensor v_w,\n torch::Tensor gate_w,\n torch::Tensor gate_b,\n torch::Tensor out_w,\n 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 <cmath>\n\n#ifndef CUDART_INF_F\n#define CUDART_INF_F __int_as_float(0x7f800000)\n#endif\n\n__global__ void ln_project_kernel(const float* __restrict__ x,\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 float* __restrict__ q,\n float* __restrict__ k,\n float* __restrict__ v,\n float* __restrict__ g,\n int B, int S, int N, int D, int H, int HD) {\n int token = blockIdx.x; // layout (B,N,S)\n int s = token % S;\n int tmp0 = token / S;\n int n = tmp0 % N;\n int b = tmp0 / N;\n int tid = threadIdx.x;\n\n __shared__ float red[256];\n __shared__ float xbuf[64];\n __shared__ float mean_s;\n __shared__ float rstd_s;\n\n float val = 0.0f;\n if (tid < D) {\n val = x[((b * S + s) * N + n) * D + tid];\n }\n red[tid] = (tid < D) ? val : 0.0f;\n __syncthreads();\n for (int off = 128; off > 0; off >>= 1) {\n if (tid < off) red[tid] += red[tid + off];\n __syncthreads();\n }\n if (tid == 0) mean_s = red[0] / (float)D;\n __syncthreads();\n float mean = mean_s;\n\n float diff = 0.0f;\n if (tid < D) {\n float xv = x[((b * S + s) * N + n) * D + tid];\n diff = xv - mean;\n }\n red[tid] = (tid < D) ? diff * diff : 0.0f;\n __syncthreads();\n for (int off = 128; off > 0; off >>= 1) {\n if (tid < off) red[tid] += red[tid + off];\n __syncthreads();\n }\n if (tid == 0) rstd_s = rsqrtf(red[0] / (float)D + 1.0e-5f);\n __syncthreads();\n float rstd = rstd_s;\n\n if (tid < D) {\n float xv = x[((b * S + s) * N + n) * D + tid];\n xbuf[tid] = (xv - mean) * rstd * ln_w[tid] + ln_b[tid];\n }\n __syncthreads();\n\n if (tid < 256) {\n int proj = tid >> 6; // 0 q, 1 k, 2 v, 3 gate\n int od = tid & 63;\n const float* w = q_w;\n if (proj == 1) w = k_w;\n else if (proj == 2) w = v_w;\n else if (proj == 3) w = gate_w;\n float acc = 0.0f;\n #pragma unroll\n for (int c = 0; c < 64; ++c) {\n acc += xbuf[c] * w[od * D + c];\n }\n if (proj == 3) {\n acc += gate_b[od];\n acc = 1.0f / (1.0f + expf(-acc));\n }\n int hh = od / HD;\n int dd = od - hh * HD;\n int oidx = (((b * N + n) * H + hh) * S + s) * HD + dd;\n if (proj == 0) q[oidx] = acc;\n else if (proj == 1) k[oidx] = acc;\n else if (proj == 2) v[oidx] = acc;\n else g[oidx] = acc;\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__ g,\n const float* __restrict__ mask,\n float* __restrict__ tmp,\n int B, int S, int N, int D, int H, int HD) {\n int idx = blockIdx.x; // (B,N,H,S_i)\n int i = idx % S;\n int t0 = idx / S;\n int h = t0 % H;\n t0 /= H;\n int n = t0 % N;\n int b = t0 / N;\n int tid = threadIdx.x; // 0..HD-1\n\n __shared__ float part[16];\n __shared__ float scores[8];\n __shared__ float weights[8];\n\n int qi_base = (((b * N + n) * H + h) * S + i) * HD;\n #pragma unroll\n for (int j = 0; j < 8; ++j) {\n if (j < S) {\n int kj_base = (((b * N + n) * H + h) * S + j) * HD;\n float prod = (tid < HD) ? q[qi_base + tid] * k[kj_base + tid] : 0.0f;\n part[tid] = prod;\n __syncthreads();\n if (tid < 8) part[tid] += part[tid + 8];\n __syncthreads();\n if (tid < 4) part[tid] += part[tid + 4];\n __syncthreads();\n if (tid < 2) part[tid] += part[tid + 2];\n __syncthreads();\n if (tid == 0) {\n float m = mask[(b * S + j) * N + n];\n scores[j] = (m == 0.0f) ? -CUDART_INF_F : (part[0] + part[1]) * rsqrtf((float)HD);\n }\n __syncthreads();\n }\n }\n\n if (tid == 0) {\n float mx = -CUDART_INF_F;\n for (int j = 0; j < S; ++j) mx = fmaxf(mx, scores[j]);\n float sum = 0.0f;\n for (int j = 0; j < S; ++j) {\n float e = expf(scores[j] - mx);\n weights[j] = e;\n sum += e;\n }\n float inv = 1.0f / sum;\n for (int j = 0; j < S; ++j) weights[j] *= inv;\n }\n __syncthreads();\n\n if (tid < HD) {\n float acc = 0.0f;\n #pragma unroll\n for (int j = 0; j < 8; ++j) {\n if (j < S) {\n int vj_base = (((b * N + n) * H + h) * S + j) * HD;\n acc += weights[j] * v[vj_base + tid];\n }\n }\n acc *= g[qi_base + tid];\n tmp[((b * N + n) * S + i) * D + h * HD + tid] = acc;\n }\n}\n\n__global__ void out_proj_kernel(const float* __restrict__ tmp,\n const float* __restrict__ out_w,\n const float* __restrict__ out_b,\n float* __restrict__ out,\n int B, int S, int N, int D) {\n int token = blockIdx.x; // (B,N,S)\n int s = token % S;\n int t0 = token / S;\n int n = t0 % N;\n int b = t0 / N;\n int tid = threadIdx.x;\n __shared__ float xb[64];\n if (tid < D) xb[tid] = tmp[((b * N + n) * S + s) * D + tid];\n __syncthreads();\n if (tid < D) {\n float acc = out_b[tid];\n #pragma unroll\n for (int c = 0; c < 64; ++c) {\n acc += xb[c] * out_w[tid * D + c];\n }\n out[((b * S + s) * N + n) * D + tid] = acc;\n }\n}\n\ntorch::Tensor forward_cuda(torch::Tensor msa_repr,\n torch::Tensor msa_mask,\n torch::Tensor ln_w,\n torch::Tensor ln_b,\n torch::Tensor q_w,\n torch::Tensor k_w,\n torch::Tensor v_w,\n torch::Tensor gate_w,\n torch::Tensor gate_b,\n torch::Tensor out_w,\n torch::Tensor out_b,\n int64_t num_heads) {\n int B = (int)msa_repr.size(0);\n int S = (int)msa_repr.size(1);\n int N = (int)msa_repr.size(2);\n int D = (int)msa_repr.size(3);\n int H = (int)num_heads;\n int HD = D / H;\n\n auto opts = msa_repr.options();\n auto q = torch::empty({B, N, H, S, HD}, opts);\n auto k = torch::empty({B, N, H, S, HD}, opts);\n auto v = torch::empty({B, N, H, S, HD}, opts);\n auto g = torch::empty({B, N, H, S, HD}, opts);\n auto tmp = torch::empty({B, N, S, D}, opts);\n auto out = torch::empty_like(msa_repr);\n\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n int tokens = B * N * S;\n ln_project_kernel<<<tokens, 256, 0, stream>>>(\n msa_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>(),\n q.data_ptr<float>(), k.data_ptr<float>(), v.data_ptr<float>(), g.data_ptr<float>(),\n B, S, N, D, H, HD);\n\n attention_kernel<<<B * N * H * S, 16, 0, stream>>>(\n q.data_ptr<float>(), k.data_ptr<float>(), v.data_ptr<float>(), g.data_ptr<float>(),\n msa_mask.data_ptr<float>(), tmp.data_ptr<float>(), B, S, N, D, H, HD);\n\n out_proj_kernel<<<tokens, 64, 0, stream>>>(\n tmp.data_ptr<float>(), out_w.data_ptr<float>(), out_b.data_ptr<float>(),\n out.data_ptr<float>(), B, S, N, D);\n return out;\n}\n'''\n\n_ext = load_inline(\n name='col_gated_attn_fused_ext_v1',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['forward_cuda'],\n extra_cflags=['-O3'],\n extra_cuda_cflags=['-O3'],\n with_cuda=True,\n verbose=False,\n)\n\n\nclass ModelNew(nn.Module):\n def __init__(self, msa_dim, num_heads, dropout=0.0):\n super().__init__()\n self.num_heads = num_heads\n self.head_dim = msa_dim // num_heads\n assert msa_dim % num_heads == 0\n self.layer_norm = nn.LayerNorm(msa_dim)\n self.query = nn.Linear(msa_dim, msa_dim, bias=False)\n self.key = nn.Linear(msa_dim, msa_dim, bias=False)\n self.value = nn.Linear(msa_dim, msa_dim, bias=False)\n self.gate = nn.Linear(msa_dim, msa_dim)\n self.out_proj = nn.Linear(msa_dim, msa_dim)\n self.dropout = nn.Dropout(dropout)\n\n def forward(self, msa_repr: torch.Tensor, msa_mask: torch.Tensor) -> torch.Tensor:\n return _ext.forward_cuda(\n msa_repr, msa_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.out_proj.weight, self.out_proj.bias,\n int(self.num_heads),\n )\n"
}