call → compile_kernel
callcompile_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 <cuda_runtime.h>\n#include <cublasLt.h>\n#include <mutex>\n\nvoid launch_adjust_bias(const float* bias, float* adj, int n, float sub, float mul, cudaStream_t stream);\n\n#define TORCH_CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be a CUDA tensor\")\n#define CHECK_CUBLAS(call) do { cublasStatus_t st = (call); TORCH_CHECK(st == CUBLAS_STATUS_SUCCESS, \"cuBLASLt error: \", (int)st); } while(0)\n\nstruct LtCache {\n cublasLtHandle_t handle = nullptr;\n cublasLtMatmulPreference_t pref = nullptr;\n cublasLtMatmulAlgo_t algo;\n bool has_algo = false;\n int64_t m=0,n=0,k=0;\n std::mutex mu;\n};\n\nstatic LtCache cache;\n\nstatic void ensure_handle() {\n if (cache.handle == nullptr) {\n CHECK_CUBLAS(cublasLtCreate(&cache.handle));\n CHECK_CUBLAS(cublasLtMatmulPreferenceCreate(&cache.pref));\n size_t workspaceSize = 32 * 1024 * 1024;\n CHECK_CUBLAS(cublasLtMatmulPreferenceSetAttribute(cache.pref, CUBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES, &workspaceSize, sizeof(workspaceSize)));\n }\n}\n\nstatic void set_row_major(cublasLtMatrixLayout_t layout) {\n cublasLtOrder_t order = CUBLASLT_ORDER_ROW;\n CHECK_CUBLAS(cublasLtMatrixLayoutSetAttribute(layout, CUBLASLT_MATRIX_LAYOUT_ORDER, &order, sizeof(order)));\n}\n\ntorch::Tensor linear_fused(torch::Tensor x, torch::Tensor weight, torch::Tensor bias, double subtract_value, double multiply_value) {\n TORCH_CHECK_CUDA(x); TORCH_CHECK_CUDA(weight); TORCH_CHECK_CUDA(bias);\n TORCH_CHECK(x.scalar_type() == torch::kFloat32, \"x must be fp32\");\n TORCH_CHECK(weight.scalar_type() == torch::kFloat32 && bias.scalar_type() == torch::kFloat32, \"params must be fp32\");\n TORCH_CHECK(x.is_contiguous() && weight.is_contiguous() && bias.is_contiguous(), \"tensors must be contiguous\");\n int64_t m = x.size(0);\n int64_t k = x.size(1);\n int64_t n = weight.size(0);\n TORCH_CHECK(weight.size(1) == k && bias.numel() == n, \"shape mismatch\");\n\n auto y = torch::empty({m, n}, x.options());\n auto adj_bias = torch::empty({n}, bias.options());\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n launch_adjust_bias(bias.data_ptr<float>(), adj_bias.data_ptr<float>(), (int)n, (float)subtract_value, (float)multiply_value, stream);\n\n cublasLtMatmulDesc_t opDesc;\n cublasLtMatrixLayout_t aDesc, bDesc, cDesc;\n CHECK_CUBLAS(cublasLtMatmulDescCreate(&opDesc, CUBLAS_COMPUTE_32F_FAST_TF32, CUDA_R_32F));\n cublasOperation_t transa = CUBLAS_OP_N;\n cublasOperation_t transb = CUBLAS_OP_T;\n CHECK_CUBLAS(cublasLtMatmulDescSetAttribute(opDesc, CUBLASLT_MATMUL_DESC_TRANSA, &transa, sizeof(transa)));\n CHECK_CUBLAS(cublasLtMatmulDescSetAttribute(opDesc, CUBLASLT_MATMUL_DESC_TRANSB, &transb, sizeof(transb)));\n cublasLtEpilogue_t epi = CUBLASLT_EPILOGUE_RELU_BIAS;\n CHECK_CUBLAS(cublasLtMatmulDescSetAttribute(opDesc, CUBLASLT_MATMUL_DESC_EPILOGUE, &epi, sizeof(epi)));\n const void* bias_ptr = (const void*)adj_bias.data_ptr<float>();\n CHECK_CUBLAS(cublasLtMatmulDescSetAttribute(opDesc, CUBLASLT_MATMUL_DESC_BIAS_POINTER, &bias_ptr, sizeof(bias_ptr)));\n\n CHECK_CUBLAS(cublasLtMatrixLayoutCreate(&aDesc, CUDA_R_32F, m, k, k));\n CHECK_CUBLAS(cublasLtMatrixLayoutCreate(&bDesc, CUDA_R_32F, n, k, k));\n CHECK_CUBLAS(cublasLtMatrixLayoutCreate(&cDesc, CUDA_R_32F, m, n, n));\n set_row_major(aDesc); set_row_major(bDesc); set_row_major(cDesc);\n\n ensure_handle();\n cublasLtMatmulAlgo_t algo_local;\n {\n std::lock_guard<std::mutex> lock(cache.mu);\n if (!cache.has_algo || cache.m != m || cache.n != n || cache.k != k) {\n cublasLtMatmulHeuristicResult_t heur;\n int returned = 0;\n CHECK_CUBLAS(cublasLtMatmulAlgoGetHeuristic(cache.handle, opDesc, aDesc, bDesc, cDesc, cDesc, cache.pref, 1, &heur, &returned));\n TORCH_CHECK(returned > 0, \"no cuBLASLt algorithm found\");\n cache.algo = heur.algo;\n cache.has_algo = true; cache.m=m; cache.n=n; cache.k=k;\n }\n algo_local = cache.algo;\n }\n\n auto workspace = torch::empty({32 * 1024 * 1024}, torch::TensorOptions().device(x.device()).dtype(torch::kUInt8));\n float alpha = (float)multiply_value;\n float beta = 0.0f;\n CHECK_CUBLAS(cublasLtMatmul(cache.handle, opDesc,\n &alpha,\n x.data_ptr<float>(), aDesc,\n weight.data_ptr<float>(), bDesc,\n &beta,\n y.data_ptr<float>(), cDesc,\n y.data_ptr<float>(), cDesc,\n &algo_local,\n workspace.data_ptr(), 32 * 1024 * 1024,\n stream));\n\n CHECK_CUBLAS(cublasLtMatmulDescDestroy(opDesc));\n CHECK_CUBLAS(cublasLtMatrixLayoutDestroy(aDesc));\n CHECK_CUBLAS(cublasLtMatrixLayoutDestroy(bDesc));\n CHECK_CUBLAS(cublasLtMatrixLayoutDestroy(cDesc));\n return y;\n}\n'''\n\n_cuda_src = r'''\n#include <cuda_runtime.h>\n\n__global__ void adjust_bias_kernel(const float* __restrict__ bias, float* __restrict__ adj, int n, float sub, float mul) {\n int i = blockIdx.x * blockDim.x + threadIdx.x;\n if (i < n) adj[i] = (bias[i] - sub) * mul;\n}\n\nvoid launch_adjust_bias(const float* bias, float* adj, int n, float sub, float mul, cudaStream_t stream) {\n int threads = 256;\n int blocks = (n + threads - 1) / threads;\n adjust_bias_kernel<<<blocks, threads, 0, stream>>>(bias, adj, n, sub, mul);\n}\n'''\n\n_ext = load_inline(name='linear_fused_cublaslt_ext_v1',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['linear_fused'],\n extra_cflags=['-O3'],\n extra_cuda_cflags=['-O3'],\n extra_ldflags=['-lcublas', '-lcublasLt'],\n with_cuda=True,\n verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, in_features, out_features, subtract_value, multiply_value):\n super(ModelNew, self).__init__()\n self.linear = nn.Linear(in_features, out_features)\n self.subtract_value = subtract_value\n self.multiply_value = multiply_value\n def forward(self, x):\n return _ext.linear_fused(x, self.linear.weight, self.linear.bias, float(self.subtract_value), float(self.multiply_value))\n"
}