call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\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\n__inline__ __device__ float warp_reduce_sum(float v) {\n for (int offset = 16; offset > 0; offset >>= 1) {\n v += __shfl_down_sync(0xffffffff, v, offset);\n }\n return v;\n}\n\n__device__ __forceinline__ float sigmoidf_stable(float x) {\n return 1.0f / (1.0f + expf(-x));\n}\n\n__device__ void grid_barrier(unsigned int* bar, int nblocks) {\n __syncthreads();\n __threadfence();\n if (threadIdx.x == 0) {\n unsigned int my_sense = bar[1];\n unsigned int ticket = atomicAdd(&bar[0], 1u);\n if (ticket == (unsigned int)(nblocks - 1)) {\n bar[0] = 0u;\n __threadfence();\n atomicAdd(&bar[1], 1u);\n } else {\n while (bar[1] == my_sense) { }\n }\n }\n __syncthreads();\n}\n\n__global__ void lstm_layer_kernel(\n const float* __restrict__ inp,\n const float* __restrict__ h0,\n const float* __restrict__ c0,\n const float* __restrict__ w_ih,\n const float* __restrict__ w_hh,\n const float* __restrict__ b_ih,\n const float* __restrict__ b_hh,\n float* __restrict__ out,\n float* __restrict__ hA,\n float* __restrict__ hB,\n float* __restrict__ cA,\n float* __restrict__ cB,\n unsigned int* __restrict__ bar,\n int B, int T, int K, int H, int layer_idx, int nblocks)\n{\n int tid = threadIdx.x;\n int lane = tid & 31;\n int warp_in_block = tid >> 5;\n int warps_per_block = blockDim.x >> 5;\n int warp_global = blockIdx.x * warps_per_block + warp_in_block;\n int total_warps = gridDim.x * warps_per_block;\n int BH = B * H;\n\n // initialize state buffers from h0/c0 for this layer\n for (int idx = blockIdx.x * blockDim.x + tid; idx < BH; idx += gridDim.x * blockDim.x) {\n int b = idx / H;\n int h = idx - b * H;\n int off = (layer_idx * B + b) * H + h;\n hA[idx] = h0[off];\n cA[idx] = c0[off];\n }\n grid_barrier(bar, nblocks);\n\n const float* hprev = hA;\n float* hnew = hB;\n const float* cprev = cA;\n float* cnew = cB;\n\n for (int t = 0; t < T; ++t) {\n for (int cell = warp_global; cell < BH; cell += total_warps) {\n int b = cell / H;\n int h = cell - b * H;\n float s0 = b_ih[h] + b_hh[h];\n float s1 = b_ih[H + h] + b_hh[H + h];\n float s2 = b_ih[2*H + h] + b_hh[2*H + h];\n float s3 = b_ih[3*H + h] + b_hh[3*H + h];\n\n const float* xptr = inp + ((b * T + t) * K);\n const float* wi0 = w_ih + h * K;\n const float* wi1 = w_ih + (H + h) * K;\n const float* wi2 = w_ih + (2*H + h) * K;\n const float* wi3 = w_ih + (3*H + h) * K;\n for (int k = lane; k < K; k += 32) {\n float xv = xptr[k];\n s0 = fmaf(xv, wi0[k], s0);\n s1 = fmaf(xv, wi1[k], s1);\n s2 = fmaf(xv, wi2[k], s2);\n s3 = fmaf(xv, wi3[k], s3);\n }\n const float* hhptr = hprev + b * H;\n const float* wh0 = w_hh + h * H;\n const float* wh1 = w_hh + (H + h) * H;\n const float* wh2 = w_hh + (2*H + h) * H;\n const float* wh3 = w_hh + (3*H + h) * H;\n for (int k = lane; k < H; k += 32) {\n float hv = hhptr[k];\n s0 = fmaf(hv, wh0[k], s0);\n s1 = fmaf(hv, wh1[k], s1);\n s2 = fmaf(hv, wh2[k], s2);\n s3 = fmaf(hv, wh3[k], s3);\n }\n s0 = warp_reduce_sum(s0);\n s1 = warp_reduce_sum(s1);\n s2 = warp_reduce_sum(s2);\n s3 = warp_reduce_sum(s3);\n if (lane == 0) {\n float ig = sigmoidf_stable(s0);\n float fg = sigmoidf_stable(s1);\n float gg = tanhf(s2);\n float og = sigmoidf_stable(s3);\n float cv = fg * cprev[cell] + ig * gg;\n float hv = og * tanhf(cv);\n cnew[cell] = cv;\n hnew[cell] = hv;\n out[(b * T + t) * H + h] = hv;\n }\n }\n grid_barrier(bar, nblocks);\n const float* tmp_h_prev = hprev; hprev = hnew; hnew = (float*)tmp_h_prev;\n const float* tmp_c_prev = cprev; cprev = cnew; cnew = (float*)tmp_c_prev;\n }\n}\n\n__global__ void fc_kernel(const float* __restrict__ seq,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ y,\n int B, int T, int H, int O) {\n int tid = threadIdx.x;\n int bo = blockIdx.x;\n int b = bo / O;\n int o = bo - b * O;\n float sum = 0.0f;\n const float* x = seq + ((b * T + (T - 1)) * H);\n const float* ww = w + o * H;\n for (int k = tid; k < H; k += blockDim.x) {\n sum = fmaf(x[k], ww[k], sum);\n }\n // block reduce 128 threads using shared memory\n __shared__ float smem[128];\n smem[tid] = sum;\n __syncthreads();\n for (int s = blockDim.x/2; s > 32; s >>= 1) {\n if (tid < s) smem[tid] += smem[tid+s];\n __syncthreads();\n }\n float v = smem[tid];\n if (tid < 32) {\n v = warp_reduce_sum(v);\n if (tid == 0) y[b * O + o] = v + bias[o];\n }\n}\n\ntorch::Tensor lstm6_forward(torch::Tensor x, torch::Tensor h0, torch::Tensor c0,\n torch::Tensor w_ih0, torch::Tensor w_hh0, torch::Tensor b_ih0, torch::Tensor b_hh0,\n torch::Tensor w_ih1, torch::Tensor w_hh1, torch::Tensor b_ih1, torch::Tensor b_hh1,\n torch::Tensor w_ih2, torch::Tensor w_hh2, torch::Tensor b_ih2, torch::Tensor b_hh2,\n torch::Tensor w_ih3, torch::Tensor w_hh3, torch::Tensor b_ih3, torch::Tensor b_hh3,\n torch::Tensor w_ih4, torch::Tensor w_hh4, torch::Tensor b_ih4, torch::Tensor b_hh4,\n torch::Tensor w_ih5, torch::Tensor w_hh5, torch::Tensor b_ih5, torch::Tensor b_hh5,\n torch::Tensor fc_w, torch::Tensor fc_b) {\n\n int B = x.size(0);\n int T = x.size(1);\n int K0 = x.size(2);\n int H = w_hh0.size(1);\n int O = fc_w.size(0);\n auto opts = x.options();\n auto tmp1 = torch::empty({B, T, H}, opts);\n auto tmp2 = torch::empty({B, T, H}, opts);\n auto hA = torch::empty({B, H}, opts);\n auto hB = torch::empty({B, H}, opts);\n auto cA = torch::empty({B, H}, opts);\n auto cB = torch::empty({B, H}, opts);\n auto bar = torch::zeros({2}, torch::TensorOptions().dtype(torch::kUInt32).device(x.device()));\n auto y = torch::empty({B, O}, opts);\n\n int threads = 128;\n int blocks = 80;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n\n lstm_layer_kernel<<<blocks, threads, 0, stream>>>(x.data_ptr<float>(), h0.data_ptr<float>(), c0.data_ptr<float>(),\n w_ih0.data_ptr<float>(), w_hh0.data_ptr<float>(), b_ih0.data_ptr<float>(), b_hh0.data_ptr<float>(),\n tmp1.data_ptr<float>(), hA.data_ptr<float>(), hB.data_ptr<float>(), cA.data_ptr<float>(), cB.data_ptr<float>(),\n (unsigned int*)bar.data_ptr<unsigned int>(), B, T, K0, H, 0, blocks);\n lstm_layer_kernel<<<blocks, threads, 0, stream>>>(tmp1.data_ptr<float>(), h0.data_ptr<float>(), c0.data_ptr<float>(),\n w_ih1.data_ptr<float>(), w_hh1.data_ptr<float>(), b_ih1.data_ptr<float>(), b_hh1.data_ptr<float>(),\n tmp2.data_ptr<float>(), hA.data_ptr<float>(), hB.data_ptr<float>(), cA.data_ptr<float>(), cB.data_ptr<float>(),\n (unsigned int*)bar.data_ptr<unsigned int>(), B, T, H, H, 1, blocks);\n lstm_layer_kernel<<<blocks, threads, 0, stream>>>(tmp2.data_ptr<float>(), h0.data_ptr<float>(), c0.data_ptr<float>(),\n w_ih2.data_ptr<float>(), w_hh2.data_ptr<float>(), b_ih2.data_ptr<float>(), b_hh2.data_ptr<float>(),\n tmp1.data_ptr<float>(), hA.data_ptr<float>(), hB.data_ptr<float>(), cA.data_ptr<float>(), cB.data_ptr<float>(),\n (unsigned int*)bar.data_ptr<unsigned int>(), B, T, H, H, 2, blocks);\n lstm_layer_kernel<<<blocks, threads, 0, stream>>>(tmp1.data_ptr<float>(), h0.data_ptr<float>(), c0.data_ptr<float>(),\n w_ih3.data_ptr<float>(), w_hh3.data_ptr<float>(), b_ih3.data_ptr<float>(), b_hh3.data_ptr<float>(),\n tmp2.data_ptr<float>(), hA.data_ptr<float>(), hB.data_ptr<float>(), cA.data_ptr<float>(), cB.data_ptr<float>(),\n (unsigned int*)bar.data_ptr<unsigned int>(), B, T, H, H, 3, blocks);\n lstm_layer_kernel<<<blocks, threads, 0, stream>>>(tmp2.data_ptr<float>(), h0.data_ptr<float>(), c0.data_ptr<float>(),\n w_ih4.data_ptr<float>(), w_hh4.data_ptr<float>(), b_ih4.data_ptr<float>(), b_hh4.data_ptr<float>(),\n tmp1.data_ptr<float>(), hA.data_ptr<float>(), hB.data_ptr<float>(), cA.data_ptr<float>(), cB.data_ptr<float>(),\n (unsigned int*)bar.data_ptr<unsigned int>(), B, T, H, H, 4, blocks);\n lstm_layer_kernel<<<blocks, threads, 0, stream>>>(tmp1.data_ptr<float>(), h0.data_ptr<float>(), c0.data_ptr<float>(),\n w_ih5.data_ptr<float>(), w_hh5.data_ptr<float>(), b_ih5.data_ptr<float>(), b_hh5.data_ptr<float>(),\n tmp2.data_ptr<float>(), hA.data_ptr<float>(), hB.data_ptr<float>(), cA.data_ptr<float>(), cB.data_ptr<float>(),\n (unsigned int*)bar.data_ptr<unsigned int>(), B, T, H, H, 5, blocks);\n\n fc_kernel<<<B * O, 128, 0, stream>>>(tmp2.data_ptr<float>(), fc_w.data_ptr<float>(), fc_b.data_ptr<float>(), y.data_ptr<float>(), B, T, H, O);\n return y;\n}\n'''\n\n_ext = load_inline(\n name='lstm6_custom_ext_v1',\n cpp_sources='',\n cuda_sources=_cuda_src,\n functions=['lstm6_forward'],\n extra_cuda_cflags=['-O3'],\n extra_cflags=['-O3'],\n with_cuda=True,\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, input_size, hidden_size, num_layers, output_size, dropout=0.0):\n super(ModelNew, self).__init__()\n self.hidden_size = hidden_size\n self.num_layers = num_layers\n self.lstm = nn.LSTM(input_size, hidden_size, num_layers,\n batch_first=True, dropout=dropout, bidirectional=False)\n self.fc = nn.Linear(hidden_size, output_size)\n def forward(self, x, h0=None, c0=None):\n batch_size = x.size(0)\n if h0 is None:\n h0 = torch.randn(self.num_layers, batch_size, self.hidden_size, device=x.device)\n if c0 is None:\n c0 = torch.randn(self.num_layers, batch_size, self.hidden_size, device=x.device)\n if self.num_layers == 6 and self.hidden_size == 256 and x.is_cuda and x.dtype == torch.float32:\n return _ext.lstm6_forward(x.contiguous(), h0.contiguous(), c0.contiguous(),\n self.lstm.weight_ih_l0, self.lstm.weight_hh_l0, self.lstm.bias_ih_l0, self.lstm.bias_hh_l0,\n self.lstm.weight_ih_l1, self.lstm.weight_hh_l1, self.lstm.bias_ih_l1, self.lstm.bias_hh_l1,\n self.lstm.weight_ih_l2, self.lstm.weight_hh_l2, self.lstm.bias_ih_l2, self.lstm.bias_hh_l2,\n self.lstm.weight_ih_l3, self.lstm.weight_hh_l3, self.lstm.bias_ih_l3, self.lstm.bias_hh_l3,\n self.lstm.weight_ih_l4, self.lstm.weight_hh_l4, self.lstm.bias_ih_l4, self.lstm.bias_hh_l4,\n self.lstm.weight_ih_l5, self.lstm.weight_hh_l5, self.lstm.bias_ih_l5, self.lstm.bias_hh_l5,\n self.fc.weight, self.fc.bias)\n out, _ = self.lstm(x, (h0, c0))\n return self.fc(out[:, -1, :])\n"
}