call → compile_kernel
callcompile_kernel
{
"kernel_code": "import os\nos.makedirs('/scratch/abaner/tmp', exist_ok=True)\nos.environ['TMPDIR'] = '/scratch/abaner/tmp'\nos.environ['MAX_JOBS'] = '1'\nimport torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_src = r'''\n#include <torch/extension.h>\ntorch::Tensor linear_relu_div_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, torch::Tensor scaled_bias, double divisor);\n'''\n\ncuda_src = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda_runtime.h>\n#include <cublasLt.h>\n#include <mutex>\n#include <climits>\n\n#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be a CUDA tensor\")\n#define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x \" must be contiguous\")\n#define CHECK_FLOAT(x) TORCH_CHECK(x.scalar_type() == at::kFloat, #x \" must be float32\")\n\nstatic cublasLtHandle_t ltHandle = nullptr;\nstatic std::once_flag handle_once;\n\nstatic void check_cublas(cublasStatus_t status, const char* msg) {\n TORCH_CHECK(status == CUBLAS_STATUS_SUCCESS, msg, \" cublas status \", (int)status);\n}\n\n__global__ void scale_bias_kernel(const float* __restrict__ b, float* __restrict__ sb, int n, float inv) {\n int i = blockIdx.x * blockDim.x + threadIdx.x;\n if (i < n) sb[i] = b[i] * inv;\n}\n\ntorch::Tensor linear_relu_div_cuda(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, torch::Tensor scaled_bias, double divisor) {\n CHECK_CUDA(x); CHECK_CUDA(weight); CHECK_CUDA(bias); CHECK_CUDA(scaled_bias);\n CHECK_CONTIGUOUS(x); CHECK_CONTIGUOUS(weight); CHECK_CONTIGUOUS(bias); CHECK_CONTIGUOUS(scaled_bias);\n CHECK_FLOAT(x); CHECK_FLOAT(weight); CHECK_FLOAT(bias); CHECK_FLOAT(scaled_bias);\n int64_t M64 = x.size(0), K64 = x.size(1), N64 = weight.size(0);\n TORCH_CHECK(x.dim() == 2 && weight.dim() == 2 && bias.dim() == 1, \"bad dims\");\n TORCH_CHECK(weight.size(1) == K64 && bias.size(0) == N64 && scaled_bias.numel() >= N64, \"shape mismatch\");\n int M=(int)M64, N=(int)N64, K=(int)K64;\n auto out = torch::empty({M64, N64}, x.options());\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n float inv = 1.0f / (float)divisor;\n scale_bias_kernel<<<(N + 255) / 256, 256, 0, stream>>>(bias.data_ptr<float>(), scaled_bias.data_ptr<float>(), N, inv);\n C10_CUDA_KERNEL_LAUNCH_CHECK();\n\n std::call_once(handle_once, [](){ check_cublas(cublasLtCreate(<Handle), \"cublasLtCreate failed\"); });\n\n cublasLtMatmulDesc_t opDesc;\n cublasLtMatrixLayout_t aDesc, bDesc, cDesc;\n check_cublas(cublasLtMatmulDescCreate(&opDesc, CUBLAS_COMPUTE_32F_FAST_TF32, CUDA_R_32F), \"op desc create failed\");\n cublasOperation_t transa = CUBLAS_OP_N, transb = CUBLAS_OP_T;\n check_cublas(cublasLtMatmulDescSetAttribute(opDesc, CUBLASLT_MATMUL_DESC_TRANSA, &transa, sizeof(transa)), \"set transa failed\");\n check_cublas(cublasLtMatmulDescSetAttribute(opDesc, CUBLASLT_MATMUL_DESC_TRANSB, &transb, sizeof(transb)), \"set transb failed\");\n cublasLtEpilogue_t epi = CUBLASLT_EPILOGUE_RELU_BIAS;\n check_cublas(cublasLtMatmulDescSetAttribute(opDesc, CUBLASLT_MATMUL_DESC_EPILOGUE, &epi, sizeof(epi)), \"set epilogue failed\");\n void* bias_ptr = (void*)scaled_bias.data_ptr<float>();\n check_cublas(cublasLtMatmulDescSetAttribute(opDesc, CUBLASLT_MATMUL_DESC_BIAS_POINTER, &bias_ptr, sizeof(bias_ptr)), \"set bias failed\");\n\n check_cublas(cublasLtMatrixLayoutCreate(&aDesc, CUDA_R_32F, M, K, K), \"a desc create failed\");\n check_cublas(cublasLtMatrixLayoutCreate(&bDesc, CUDA_R_32F, N, K, K), \"b desc create failed\");\n check_cublas(cublasLtMatrixLayoutCreate(&cDesc, CUDA_R_32F, M, N, N), \"c desc create failed\");\n cublasLtOrder_t order = CUBLASLT_ORDER_ROW;\n check_cublas(cublasLtMatrixLayoutSetAttribute(aDesc, CUBLASLT_MATRIX_LAYOUT_ORDER, &order, sizeof(order)), \"a order failed\");\n check_cublas(cublasLtMatrixLayoutSetAttribute(bDesc, CUBLASLT_MATRIX_LAYOUT_ORDER, &order, sizeof(order)), \"b order failed\");\n check_cublas(cublasLtMatrixLayoutSetAttribute(cDesc, CUBLASLT_MATRIX_LAYOUT_ORDER, &order, sizeof(order)), \"c order failed\");\n\n cublasLtMatmulPreference_t pref;\n check_cublas(cublasLtMatmulPreferenceCreate(&pref), \"pref create failed\");\n size_t maxWorkspace = 0;\n check_cublas(cublasLtMatmulPreferenceSetAttribute(pref, CUBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES, &maxWorkspace, sizeof(maxWorkspace)), \"pref set failed\");\n cublasLtMatmulHeuristicResult_t heuristic;\n int returned = 0;\n check_cublas(cublasLtMatmulAlgoGetHeuristic(ltHandle, opDesc, aDesc, bDesc, cDesc, cDesc, pref, 1, &heuristic, &returned), \"heuristic failed\");\n TORCH_CHECK(returned > 0, \"no cublasLt algo found\");\n float alpha = inv, beta = 0.0f;\n check_cublas(cublasLtMatmul(ltHandle, opDesc, &alpha, x.data_ptr<float>(), aDesc, weight.data_ptr<float>(), bDesc, &beta, out.data_ptr<float>(), cDesc, out.data_ptr<float>(), cDesc, &heuristic.algo, nullptr, 0, stream), \"matmul failed\");\n\n cublasLtMatmulPreferenceDestroy(pref);\n cublasLtMatrixLayoutDestroy(cDesc); cublasLtMatrixLayoutDestroy(bDesc); cublasLtMatrixLayoutDestroy(aDesc); cublasLtMatmulDescDestroy(opDesc);\n return out;\n}\n'''\n_ext = load_inline(name='linear_relu_div_lt_ext_v2', cpp_sources=cpp_src, cuda_sources=cuda_src, functions=['linear_relu_div_cuda'], extra_ldflags=['-lcublasLt', '-lcublas'], extra_cuda_cflags=['-O3'], extra_cflags=['-O3'], verbose=False)\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, divisor):\n super(ModelNew, self).__init__()\n self.linear = nn.Linear(in_features, out_features)\n self.divisor = divisor\n self.register_buffer('scaled_bias', torch.empty(out_features, dtype=torch.float32), persistent=False)\n def forward(self, x):\n return _ext.linear_relu_div_cuda(x.contiguous(), self.linear.weight.contiguous(), self.linear.bias.contiguous(), self.scaled_bias, float(self.divisor))\n"
}