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#include <ATen/cuda/CUDAContext.h>\n#include <ATen/Context.h>\n#include <cublas_v2.h>\n\nvoid gelu_bias_div_launcher(torch::Tensor y, torch::Tensor bias, double inv_divisor);\n\ntorch::Tensor linear_div_gelu(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double divisor) {\n TORCH_CHECK(x.is_cuda(), \"x must be CUDA\");\n TORCH_CHECK(weight.is_cuda(), \"weight must be CUDA\");\n TORCH_CHECK(bias.is_cuda(), \"bias must be CUDA\");\n TORCH_CHECK(x.scalar_type() == torch::kFloat32, \"only float32 is supported\");\n TORCH_CHECK(weight.scalar_type() == torch::kFloat32, \"only float32 is supported\");\n TORCH_CHECK(bias.scalar_type() == torch::kFloat32, \"only float32 is supported\");\n TORCH_CHECK(x.is_contiguous(), \"x must be contiguous\");\n TORCH_CHECK(weight.is_contiguous(), \"weight must be contiguous\");\n TORCH_CHECK(bias.is_contiguous(), \"bias must be contiguous\");\n TORCH_CHECK(x.dim() == 2 && weight.dim() == 2 && bias.dim() == 1, \"bad tensor ranks\");\n\n const int64_t M64 = x.size(0);\n const int64_t K64 = x.size(1);\n const int64_t N64 = weight.size(0);\n TORCH_CHECK(weight.size(1) == K64, \"incompatible dimensions\");\n TORCH_CHECK(bias.size(0) == N64, \"incompatible bias\");\n TORCH_CHECK(M64 <= INT_MAX && N64 <= INT_MAX && K64 <= INT_MAX, \"dimensions too large\");\n const int M = static_cast<int>(M64);\n const int N = static_cast<int>(N64);\n const int K = static_cast<int>(K64);\n\n auto y = torch::empty({M64, N64}, x.options());\n\n cublasHandle_t handle = at::cuda::getCurrentCUDABlasHandle();\n cublasSetStream(handle, at::cuda::getCurrentCUDAStream());\n\n // Match PyTorch's TF32 setting for fp32 matmul as closely as possible.\n#if defined(CUBLAS_TF32_TENSOR_OP_MATH) && defined(CUBLAS_PEDANTIC_MATH)\n cublasSetMathMode(handle, at::globalContext().allowTF32CuBLAS() ? CUBLAS_TF32_TENSOR_OP_MATH : CUBLAS_PEDANTIC_MATH);\n#elif defined(CUBLAS_PEDANTIC_MATH)\n cublasSetMathMode(handle, CUBLAS_PEDANTIC_MATH);\n#else\n cublasSetMathMode(handle, CUBLAS_DEFAULT_MATH);\n#endif\n\n // Row-major y[M,N] = (x[M,K] * weight[N,K]^T) / divisor.\n // Interpreting row-major buffers as column-major gives y^T[N,M] = weight * x^T.\n const float alpha = static_cast<float>(1.0 / divisor);\n const float beta = 0.0f;\n cublasStatus_t st = cublasSgemm(\n handle,\n CUBLAS_OP_T, CUBLAS_OP_N,\n N, M, K,\n &alpha,\n weight.data_ptr<float>(), K,\n x.data_ptr<float>(), K,\n &beta,\n y.data_ptr<float>(), N);\n TORCH_CHECK(st == CUBLAS_STATUS_SUCCESS, \"cublasSgemm failed with status \", (int)st);\n\n gelu_bias_div_launcher(y, bias, 1.0 / divisor);\n return y;\n}\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <c10/cuda/CUDAException.h>\n#include <cuda_runtime.h>\n#include <math_constants.h>\n\n__global__ void gelu_bias_div_kernel(float* __restrict__ y,\n const float* __restrict__ bias,\n int M, int N, float inv_divisor) {\n const int col = blockIdx.x * blockDim.x + threadIdx.x;\n const int row = blockIdx.y;\n if (col < N && row < M) {\n const int idx = row * N + col;\n float v = y[idx] + bias[col] * inv_divisor;\n // Exact GELU: 0.5*x*(1 + erf(x/sqrt(2))).\n float r = 0.5f * v * (1.0f + erff(v * 0.70710678118654752440f));\n y[idx] = r;\n }\n}\n\nvoid gelu_bias_div_launcher(torch::Tensor y, torch::Tensor bias, double inv_divisor) {\n const int M = static_cast<int>(y.size(0));\n const int N = static_cast<int>(y.size(1));\n const dim3 block(256);\n const dim3 grid((N + block.x - 1) / block.x, M);\n gelu_bias_div_kernel<<<grid, block, 0, at::cuda::getCurrentCUDAStream()>>>(\n y.data_ptr<float>(), bias.data_ptr<float>(), M, N, static_cast<float>(inv_divisor));\n C10_CUDA_KERNEL_LAUNCH_CHECK();\n}\n'''\n\n_ext = load_inline(\n name='linear_div_gelu_fused_ext_v1',\n cpp_sources=[_cpp_src],\n cuda_sources=[_cuda_src],\n functions=['linear_div_gelu'],\n extra_cflags=['-O3'],\n extra_cuda_cflags=['-O3'],\n extra_ldflags=['-lcublas'],\n with_cuda=True,\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, input_size, output_size, divisor):\n super(ModelNew, self).__init__()\n self.linear = nn.Linear(input_size, output_size)\n self.divisor = divisor\n\n def forward(self, x):\n if not x.is_contiguous():\n x = x.contiguous()\n return _ext.linear_div_gelu(x, self.linear.weight, self.linear.bias, float(self.divisor))\n"
}