call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_src = r'''\n#include <torch/extension.h>\n\ntorch::Tensor opm_forward(torch::Tensor msa, torch::Tensor mask,\n torch::Tensor ln_w, torch::Tensor ln_b,\n torch::Tensor wa, torch::Tensor ba,\n torch::Tensor wb, torch::Tensor bb,\n torch::Tensor wo, torch::Tensor bo);\n'''\n\ncuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n__global__ void proj_kernel(const float* __restrict__ msa, const float* __restrict__ mask,\n const float* __restrict__ ln_w, const float* __restrict__ ln_b,\n const float* __restrict__ wa, const float* __restrict__ ba,\n const float* __restrict__ wb, const float* __restrict__ bb,\n float* __restrict__ A, float* __restrict__ Bp,\n int Bsz, int S, int N, int C, int H) {\n int row = blockIdx.x;\n int n = row % N;\n int tmp = row / N;\n int s = tmp % S;\n int b = tmp / S;\n const float* x = msa + (((b*S + s)*N + n)*C);\n\n __shared__ float sh[128];\n float sum = 0.0f;\n for (int c = threadIdx.x; c < C; c += blockDim.x) sum += x[c];\n sh[threadIdx.x] = sum;\n __syncthreads();\n for (int off = blockDim.x/2; off > 0; off >>= 1) {\n if (threadIdx.x < off) sh[threadIdx.x] += sh[threadIdx.x + off];\n __syncthreads();\n }\n float mean = sh[0] / (float)C;\n float ss = 0.0f;\n for (int c = threadIdx.x; c < C; c += blockDim.x) {\n float d = x[c] - mean;\n ss += d*d;\n }\n sh[threadIdx.x] = ss;\n __syncthreads();\n for (int off = blockDim.x/2; off > 0; off >>= 1) {\n if (threadIdx.x < off) sh[threadIdx.x] += sh[threadIdx.x + off];\n __syncthreads();\n }\n float rstd = rsqrtf(sh[0] / (float)C + 1.0e-5f);\n float m = mask[(b*S + s)*N + n];\n\n for (int t = threadIdx.x; t < 2*H; t += blockDim.x) {\n int is_b = (t >= H);\n int h = is_b ? (t - H) : t;\n const float* w = (is_b ? wb : wa) + h*C;\n float acc = 0.0f;\n for (int c = 0; c < C; ++c) {\n float xn = (x[c] - mean) * rstd;\n xn = xn * ln_w[c] + ln_b[c];\n acc += xn * w[c];\n }\n acc += is_b ? bb[h] : ba[h];\n acc *= m;\n float* out = (is_b ? Bp : A) + (((b*S + s)*N + n)*H + h);\n *out = acc;\n }\n}\n\n__global__ void transb_kernel(const float* __restrict__ Bp, const float* __restrict__ wo,\n float* __restrict__ T,\n int Bsz, int S, int N, int H, int P) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long total = (long long)Bsz*S*N*H*P;\n if (idx >= total) return;\n int p = idx % P;\n long long q = idx / P;\n int h = q % H;\n q /= H;\n int j = q % N;\n q /= N;\n int s = q % S;\n int b = q / S;\n const float* bv = Bp + (((b*S + s)*N + j)*H);\n const float* w = wo + p*(H*H) + h*H;\n float acc = 0.0f;\n #pragma unroll\n for (int k = 0; k < 32; ++k) {\n if (k < H) acc += bv[k] * w[k];\n }\n T[idx] = acc;\n}\n\n__global__ void output_kernel(const float* __restrict__ A, const float* __restrict__ T,\n const float* __restrict__ mask,\n const float* __restrict__ bo,\n float* __restrict__ out,\n int Bsz, int S, int N, int H, int P) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long total = (long long)Bsz*N*N*P;\n if (idx >= total) return;\n int p = idx % P;\n long long q = idx / P;\n int j = q % N;\n q /= N;\n int i = q % N;\n int b = q / N;\n\n float acc = 0.0f;\n for (int s = 0; s < S; ++s) {\n const float* av = A + (((b*S + s)*N + i)*H);\n const float* tv = T + ((((b*S + s)*N + j)*H)*P + p);\n for (int h = 0; h < H; ++h) {\n acc += av[h] * tv[h*P];\n }\n }\n float denom = 0.0f;\n for (int s = 0; s < S; ++s) denom += mask[(b*S + s)*N + i];\n if (denom < 1.0f) denom = 1.0f;\n out[idx] = acc / denom + bo[p];\n}\n\ntorch::Tensor opm_forward(torch::Tensor msa, torch::Tensor mask,\n torch::Tensor ln_w, torch::Tensor ln_b,\n torch::Tensor wa, torch::Tensor ba,\n torch::Tensor wb, torch::Tensor bb,\n torch::Tensor wo, torch::Tensor bo) {\n int Bsz = msa.size(0);\n int S = msa.size(1);\n int N = msa.size(2);\n int C = msa.size(3);\n int H = wa.size(0);\n int P = wo.size(0);\n auto opts = msa.options();\n auto A = torch::empty({Bsz, S, N, H}, opts);\n auto Bp = torch::empty({Bsz, S, N, H}, opts);\n auto T = torch::empty({Bsz, S, N, H, P}, opts);\n auto out = torch::empty({Bsz, N, N, P}, opts);\n\n int rows = Bsz*S*N;\n proj_kernel<<<rows, 128>>>(msa.data_ptr<float>(), mask.data_ptr<float>(),\n ln_w.data_ptr<float>(), ln_b.data_ptr<float>(),\n wa.data_ptr<float>(), ba.data_ptr<float>(),\n wb.data_ptr<float>(), bb.data_ptr<float>(),\n A.data_ptr<float>(), Bp.data_ptr<float>(),\n Bsz, S, N, C, H);\n long long nt = (long long)Bsz*S*N*H*P;\n transb_kernel<<<(nt + 255)/256, 256>>>(Bp.data_ptr<float>(), wo.data_ptr<float>(), T.data_ptr<float>(), Bsz, S, N, H, P);\n long long no = (long long)Bsz*N*N*P;\n output_kernel<<<(no + 255)/256, 256>>>(A.data_ptr<float>(), T.data_ptr<float>(), mask.data_ptr<float>(), bo.data_ptr<float>(), out.data_ptr<float>(), Bsz, S, N, H, P);\n return out;\n}\n'''\n\n_ext = load_inline(name='opm_ext_v1', cpp_sources=cpp_src, cuda_sources=cuda_src,\n functions=['opm_forward'], extra_cuda_cflags=['-O3', '--use_fast_math'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, msa_dim, pair_dim, hidden_dim=32):\n super().__init__()\n self.layer_norm = nn.LayerNorm(msa_dim)\n self.proj_a = nn.Linear(msa_dim, hidden_dim)\n self.proj_b = nn.Linear(msa_dim, hidden_dim)\n self.out_proj = nn.Linear(hidden_dim * hidden_dim, pair_dim)\n\n def forward(self, msa_repr: torch.Tensor, msa_mask: torch.Tensor) -> torch.Tensor:\n return _ext.opm_forward(msa_repr.contiguous(), msa_mask.contiguous(),\n self.layer_norm.weight, self.layer_norm.bias,\n self.proj_a.weight, self.proj_a.bias,\n self.proj_b.weight, self.proj_b.bias,\n self.out_proj.weight, self.out_proj.bias)\n"
}