call → submit_kernel
callsubmit_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nimport torch.nn.functional as F\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#define COL_TILE 32\n#define TY 8\n#define ROWS_PER_BLOCK 256\n\n__global__ void partial_sums_kernel(const float* __restrict__ y,\n float* __restrict__ psum,\n float* __restrict__ psq,\n int N, int C) {\n __shared__ float sh_sum[TY][COL_TILE];\n __shared__ float sh_sq[TY][COL_TILE];\n int tx = threadIdx.x;\n int ty = threadIdx.y;\n int c = blockIdx.x * COL_TILE + tx;\n int r0 = blockIdx.y * ROWS_PER_BLOCK;\n int rend = r0 + ROWS_PER_BLOCK;\n if (rend > N) rend = N;\n\n float s = 0.0f;\n float q = 0.0f;\n if (c < C) {\n for (int r = r0 + ty; r < rend; r += TY) {\n float v = y[(long long)r * C + c];\n s += v;\n q += v * v;\n }\n }\n sh_sum[ty][tx] = s;\n sh_sq[ty][tx] = q;\n __syncthreads();\n\n if (ty < 4) { sh_sum[ty][tx] += sh_sum[ty+4][tx]; sh_sq[ty][tx] += sh_sq[ty+4][tx]; }\n __syncthreads();\n if (ty < 2) { sh_sum[ty][tx] += sh_sum[ty+2][tx]; sh_sq[ty][tx] += sh_sq[ty+2][tx]; }\n __syncthreads();\n if (ty == 0) {\n s = sh_sum[0][tx] + sh_sum[1][tx];\n q = sh_sq[0][tx] + sh_sq[1][tx];\n if (c < C) {\n psum[(long long)blockIdx.y * C + c] = s;\n psq[(long long)blockIdx.y * C + c] = q;\n }\n }\n}\n\n__global__ void final_stats_kernel(const float* __restrict__ psum,\n const float* __restrict__ psq,\n const float* __restrict__ scale,\n float* __restrict__ running_mean,\n float* __restrict__ running_var,\n float* __restrict__ mean,\n float* __restrict__ invstd,\n int N, int C, int NB,\n float momentum, float eps) {\n int c = blockIdx.x;\n int t = threadIdx.x;\n __shared__ float ss[256];\n __shared__ float qq[256];\n float s = 0.0f;\n float q = 0.0f;\n for (int b = t; b < NB; b += blockDim.x) {\n s += psum[(long long)b * C + c];\n q += psq[(long long)b * C + c];\n }\n ss[t] = s;\n qq[t] = q;\n __syncthreads();\n for (int stride = blockDim.x >> 1; stride > 0; stride >>= 1) {\n if (t < stride) {\n ss[t] += ss[t + stride];\n qq[t] += qq[t + stride];\n }\n __syncthreads();\n }\n if (t == 0) {\n float invN = 1.0f / (float)N;\n float mz = ss[0] * invN;\n float vz = qq[0] * invN - mz * mz;\n if (vz < 0.0f) vz = 0.0f;\n float sc = scale[c];\n float m = mz * sc;\n float v = vz * sc * sc;\n mean[c] = m;\n invstd[c] = 1.0f / sqrtf(v + eps);\n float unbiased = v;\n if (N > 1) unbiased = v * ((float)N / (float)(N - 1));\n running_mean[c] = running_mean[c] * (1.0f - momentum) + momentum * m;\n running_var[c] = running_var[c] * (1.0f - momentum) + momentum * unbiased;\n }\n}\n\n__global__ void train_apply_kernel(float* __restrict__ y,\n const float* __restrict__ scale,\n const float* __restrict__ gamma,\n const float* __restrict__ beta,\n const float* __restrict__ mean,\n const float* __restrict__ invstd,\n long long total, int C) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n for (; idx < total; idx += stride) {\n int c = (int)(idx % C);\n float v = y[idx] * scale[c];\n y[idx] = (v - mean[c]) * invstd[c] * gamma[c] + beta[c];\n }\n}\n\n__global__ void eval_apply_kernel(float* __restrict__ y,\n const float* __restrict__ scale,\n const float* __restrict__ gamma,\n const float* __restrict__ beta,\n const float* __restrict__ running_mean,\n const float* __restrict__ running_var,\n long long total, int C, float eps) {\n long long idx = (long long)blockIdx.x * blockDim.x + threadIdx.x;\n long long stride = (long long)blockDim.x * gridDim.x;\n for (; idx < total; idx += stride) {\n int c = (int)(idx % C);\n float v = y[idx] * scale[c];\n float inv = 1.0f / sqrtf(running_var[c] + eps);\n y[idx] = (v - running_mean[c]) * inv * gamma[c] + beta[c];\n }\n}\n\ntorch::Tensor bn_train_inplace(torch::Tensor y,\n torch::Tensor scale,\n torch::Tensor gamma,\n torch::Tensor beta,\n torch::Tensor running_mean,\n torch::Tensor running_var,\n double momentum,\n double eps) {\n const int N = (int)y.size(0);\n const int C = (int)y.size(1);\n const int NB = (N + ROWS_PER_BLOCK - 1) / ROWS_PER_BLOCK;\n auto opts = y.options();\n torch::Tensor psum = torch::empty({NB, C}, opts);\n torch::Tensor psq = torch::empty({NB, C}, opts);\n torch::Tensor mean = torch::empty({C}, opts);\n torch::Tensor invstd = torch::empty({C}, opts);\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n dim3 block(COL_TILE, TY);\n dim3 grid((C + COL_TILE - 1) / COL_TILE, NB);\n partial_sums_kernel<<<grid, block, 0, stream>>>(y.data_ptr<float>(), psum.data_ptr<float>(), psq.data_ptr<float>(), N, C);\n final_stats_kernel<<<C, 256, 0, stream>>>(psum.data_ptr<float>(), psq.data_ptr<float>(), scale.data_ptr<float>(),\n running_mean.data_ptr<float>(), running_var.data_ptr<float>(), mean.data_ptr<float>(), invstd.data_ptr<float>(),\n N, C, NB, (float)momentum, (float)eps);\n long long total = (long long)N * C;\n int threads = 256;\n int blocks = (int)((total + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n train_apply_kernel<<<blocks, threads, 0, stream>>>(y.data_ptr<float>(), scale.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), mean.data_ptr<float>(), invstd.data_ptr<float>(), total, C);\n return y;\n}\n\ntorch::Tensor bn_eval_inplace(torch::Tensor y,\n torch::Tensor scale,\n torch::Tensor gamma,\n torch::Tensor beta,\n torch::Tensor running_mean,\n torch::Tensor running_var,\n double eps) {\n const int N = (int)y.size(0);\n const int C = (int)y.size(1);\n long long total = (long long)N * C;\n int threads = 256;\n int blocks = (int)((total + threads - 1) / threads);\n if (blocks > 65535) blocks = 65535;\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n eval_apply_kernel<<<blocks, threads, 0, stream>>>(y.data_ptr<float>(), scale.data_ptr<float>(), gamma.data_ptr<float>(), beta.data_ptr<float>(), running_mean.data_ptr<float>(), running_var.data_ptr<float>(), total, C, (float)eps);\n return y;\n}\n'''\n\n_ext = load_inline(\n name='fused_scale_bn_inline_ext_v1',\n cpp_sources='',\n cuda_sources=_cuda_src,\n functions=['bn_train_inplace', 'bn_eval_inplace'],\n extra_cflags=['-O3'],\n extra_cuda_cflags=['-O3'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, scale_shape, eps=1e-5, momentum=0.1):\n super(ModelNew, self).__init__()\n self.gemm = nn.Linear(in_features, out_features)\n self.scale = nn.Parameter(torch.randn(scale_shape))\n self.bn = nn.BatchNorm1d(out_features, eps=eps, momentum=momentum)\n\n def forward(self, x):\n y = F.linear(x, self.gemm.weight, self.gemm.bias)\n if self.bn.training:\n if self.bn.track_running_stats:\n self.bn.num_batches_tracked.add_(1)\n if self.bn.momentum is None:\n mom = 1.0 / float(self.bn.num_batches_tracked.item())\n else:\n mom = float(self.bn.momentum)\n else:\n mom = 0.0 if self.bn.momentum is None else float(self.bn.momentum)\n return _ext.bn_train_inplace(y, self.scale, self.bn.weight, self.bn.bias,\n self.bn.running_mean, self.bn.running_var,\n mom, float(self.bn.eps))\n else:\n return _ext.bn_eval_inplace(y, self.scale, self.bn.weight, self.bn.bias,\n self.bn.running_mean, self.bn.running_var,\n float(self.bn.eps))\n"
}