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 triangular_forward(\n torch::Tensor pair_repr, torch::Tensor pair_mask,\n torch::Tensor ln_in_w, torch::Tensor ln_in_b,\n torch::Tensor proj_a_w, torch::Tensor proj_a_b,\n torch::Tensor gate_a_w, torch::Tensor gate_a_b,\n torch::Tensor proj_b_w, torch::Tensor proj_b_b,\n torch::Tensor gate_b_w, torch::Tensor gate_b_b,\n torch::Tensor ln_out_w, torch::Tensor ln_out_b,\n torch::Tensor out_proj_w, torch::Tensor out_proj_b,\n torch::Tensor out_gate_w, torch::Tensor out_gate_b);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda_runtime.h>\n#include <math.h>\n\nstatic __device__ __forceinline__ float sigmoidf_dev(float x) {\n return 1.0f / (1.0f + expf(-x));\n}\n\n// One block per (B,N,N) row. Computes input LayerNorm and all a/b projections.\n__global__ void compute_ab_kernel(\n const float* __restrict__ x0, const float* __restrict__ mask,\n const float* __restrict__ ln_w, const float* __restrict__ ln_b,\n const float* __restrict__ pa_w, const float* __restrict__ pa_b,\n const float* __restrict__ ga_w, const float* __restrict__ ga_b,\n const float* __restrict__ pb_w, const float* __restrict__ pb_b,\n const float* __restrict__ gb_w, const float* __restrict__ gb_b,\n float* __restrict__ a, float* __restrict__ b,\n int rows, int C, int H)\n{\n int row = blockIdx.x;\n int tid = threadIdx.x;\n __shared__ float red[128];\n __shared__ float xn[64];\n __shared__ float vals[128];\n\n float v = 0.0f;\n if (tid < C) v = x0[row * C + tid];\n red[tid] = (tid < C) ? v : 0.0f;\n __syncthreads();\n for (int s = 64; s > 0; s >>= 1) { if (tid < s) red[tid] += red[tid+s]; __syncthreads(); }\n float mean = red[0] * (1.0f / (float)C);\n\n float d = 0.0f;\n if (tid < C) { float t = v - mean; d = t * t; }\n red[tid] = (tid < C) ? d : 0.0f;\n __syncthreads();\n for (int s = 64; s > 0; s >>= 1) { if (tid < s) red[tid] += red[tid+s]; __syncthreads(); }\n float rstd = rsqrtf(red[0] * (1.0f / (float)C) + 1.0e-5f);\n\n if (tid < C) xn[tid] = (v - mean) * rstd * ln_w[tid] + ln_b[tid];\n __syncthreads();\n\n int h = tid & 31;\n int which = tid >> 5;\n if (h < H) {\n const float* w;\n const float* bias;\n if (which == 0) { w = pa_w; bias = pa_b; }\n else if (which == 1) { w = ga_w; bias = ga_b; }\n else if (which == 2) { w = pb_w; bias = pb_b; }\n else { w = gb_w; bias = gb_b; }\n float sum = bias[h];\n const float* wh = w + h * C;\n #pragma unroll\n for (int c = 0; c < 64; ++c) sum += wh[c] * xn[c];\n vals[tid] = sum;\n }\n __syncthreads();\n\n if (tid < H) {\n float m = mask[row];\n float av = vals[tid] * sigmoidf_dev(vals[32 + tid]) * m;\n float bv = vals[64 + tid] * sigmoidf_dev(vals[96 + tid]) * m;\n a[row * H + tid] = av;\n b[row * H + tid] = bv;\n }\n}\n\n// One thread per (b,i,j,h); sum over k.\n__global__ void einsum_kernel(const float* __restrict__ a, const float* __restrict__ b,\n float* __restrict__ out, int B, int N, int H) {\n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int total = B * N * N * H;\n if (idx >= total) return;\n int h = idx % H;\n int t = idx / H;\n int j = t % N;\n t /= N;\n int i = t % N;\n int bb = t / N;\n float sum = 0.0f;\n int base_a = ((bb * N + i) * N) * H + h;\n int base_b = ((bb * N + j) * N) * H + h;\n #pragma unroll\n for (int k = 0; k < 32; ++k) {\n sum += a[base_a + k * H] * b[base_b + k * H];\n }\n out[idx] = sum;\n}\n\n// One block per output row. LayerNorm over H, out projection, out gate, multiply.\n__global__ void final_kernel(\n const float* __restrict__ mid, const float* __restrict__ pair_repr,\n const float* __restrict__ ln_w, const float* __restrict__ ln_b,\n const float* __restrict__ op_w, const float* __restrict__ op_b,\n const float* __restrict__ og_w, const float* __restrict__ og_b,\n float* __restrict__ out, int rows, int C, int H)\n{\n int row = blockIdx.x;\n int tid = threadIdx.x;\n __shared__ float red[128];\n __shared__ float yn[32];\n\n float v = 0.0f;\n if (tid < H) v = mid[row * H + tid];\n red[tid] = (tid < H) ? v : 0.0f;\n __syncthreads();\n for (int s = 64; s > 0; s >>= 1) { if (tid < s) red[tid] += red[tid+s]; __syncthreads(); }\n float mean = red[0] * (1.0f / (float)H);\n\n float d = 0.0f;\n if (tid < H) { float t = v - mean; d = t * t; }\n red[tid] = (tid < H) ? d : 0.0f;\n __syncthreads();\n for (int s = 64; s > 0; s >>= 1) { if (tid < s) red[tid] += red[tid+s]; __syncthreads(); }\n float rstd = rsqrtf(red[0] * (1.0f / (float)H) + 1.0e-5f);\n if (tid < H) yn[tid] = (v - mean) * rstd * ln_w[tid] + ln_b[tid];\n __syncthreads();\n\n if (tid < C) {\n int c = tid;\n float pv = op_b[c];\n const float* ow = op_w + c * H;\n #pragma unroll\n for (int h = 0; h < 32; ++h) pv += ow[h] * yn[h];\n\n float gv = og_b[c];\n const float* gw = og_w + c * C;\n const float* xr = pair_repr + row * C;\n #pragma unroll\n for (int k = 0; k < 64; ++k) gv += gw[k] * xr[k];\n out[row * C + c] = sigmoidf_dev(gv) * pv;\n }\n}\n\ntorch::Tensor triangular_forward(\n torch::Tensor pair_repr, torch::Tensor pair_mask,\n torch::Tensor ln_in_w, torch::Tensor ln_in_b,\n torch::Tensor proj_a_w, torch::Tensor proj_a_b,\n torch::Tensor gate_a_w, torch::Tensor gate_a_b,\n torch::Tensor proj_b_w, torch::Tensor proj_b_b,\n torch::Tensor gate_b_w, torch::Tensor gate_b_b,\n torch::Tensor ln_out_w, torch::Tensor ln_out_b,\n torch::Tensor out_proj_w, torch::Tensor out_proj_b,\n torch::Tensor out_gate_w, torch::Tensor out_gate_b)\n{\n const int B = pair_repr.size(0);\n const int N = pair_repr.size(1);\n const int C = pair_repr.size(3);\n const int H = proj_a_w.size(0);\n const int rows = B * N * N;\n auto optsH = pair_repr.options();\n auto a = torch::empty({B, N, N, H}, optsH);\n auto b = torch::empty({B, N, N, H}, optsH);\n auto mid = torch::empty({B, N, N, H}, optsH);\n auto out = torch::empty_like(pair_repr);\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n\n compute_ab_kernel<<<rows, 128, 0, stream>>>(\n pair_repr.data_ptr<float>(), pair_mask.data_ptr<float>(),\n ln_in_w.data_ptr<float>(), ln_in_b.data_ptr<float>(),\n proj_a_w.data_ptr<float>(), proj_a_b.data_ptr<float>(),\n gate_a_w.data_ptr<float>(), gate_a_b.data_ptr<float>(),\n proj_b_w.data_ptr<float>(), proj_b_b.data_ptr<float>(),\n gate_b_w.data_ptr<float>(), gate_b_b.data_ptr<float>(),\n a.data_ptr<float>(), b.data_ptr<float>(), rows, C, H);\n\n int total = B * N * N * H;\n einsum_kernel<<<(total + 255) / 256, 256, 0, stream>>>(a.data_ptr<float>(), b.data_ptr<float>(), mid.data_ptr<float>(), B, N, H);\n\n final_kernel<<<rows, 128, 0, stream>>>(\n mid.data_ptr<float>(), pair_repr.data_ptr<float>(),\n ln_out_w.data_ptr<float>(), ln_out_b.data_ptr<float>(),\n out_proj_w.data_ptr<float>(), out_proj_b.data_ptr<float>(),\n out_gate_w.data_ptr<float>(), out_gate_b.data_ptr<float>(),\n out.data_ptr<float>(), rows, C, H);\n return out;\n}\n'''\n\n_ext = load_inline(\n name='tri_mul_outgoing_ext_v1',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['triangular_forward'],\n extra_cflags=['-O3'],\n extra_cuda_cflags=['-O3'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, pair_dim, hidden_dim):\n super().__init__()\n self.layer_norm_in = nn.LayerNorm(pair_dim)\n self.proj_a = nn.Linear(pair_dim, hidden_dim)\n self.gate_a = nn.Linear(pair_dim, hidden_dim)\n self.proj_b = nn.Linear(pair_dim, hidden_dim)\n self.gate_b = nn.Linear(pair_dim, hidden_dim)\n self.layer_norm_out = nn.LayerNorm(hidden_dim)\n self.out_proj = nn.Linear(hidden_dim, pair_dim)\n self.out_gate = nn.Linear(pair_dim, pair_dim)\n\n def forward(self, pair_repr: torch.Tensor, pair_mask: torch.Tensor) -> torch.Tensor:\n return _ext.triangular_forward(\n pair_repr, pair_mask,\n self.layer_norm_in.weight, self.layer_norm_in.bias,\n self.proj_a.weight, self.proj_a.bias,\n self.gate_a.weight, self.gate_a.bias,\n self.proj_b.weight, self.proj_b.bias,\n self.gate_b.weight, self.gate_b.bias,\n self.layer_norm_out.weight, self.layer_norm_out.bias,\n self.out_proj.weight, self.out_proj.bias,\n self.out_gate.weight, self.out_gate.bias,\n )\n"
}