call → run_correctness
callrun_correctness
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncuda_source = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda_runtime.h>\n#include <cublasLt.h>\n#include <cstring>\n\nstatic cublasLtHandle_t ltHandle = nullptr;\nstatic void ensure_handle(){ if(ltHandle == nullptr) cublasLtCreate(<Handle); }\n\nstruct Plan {\n bool valid = false;\n int64_t M = 0, K = 0, N = 0;\n bool relu = false;\n cublasLtMatmulDesc_t opDesc = nullptr;\n cublasLtMatrixLayout_t aDesc = nullptr, bDesc = nullptr, cDesc = nullptr;\n cublasLtMatmulAlgo_t algo;\n};\nstatic Plan plans[8];\n\nstatic Plan* get_plan(int64_t M, int64_t K, int64_t N, bool relu, const void* bias_ptr, size_t workspaceSize) {\n ensure_handle();\n for (int i=0;i<8;i++) if (plans[i].valid && plans[i].M==M && plans[i].K==K && plans[i].N==N && plans[i].relu==relu) return &plans[i];\n int slot = -1; for (int i=0;i<8;i++) if (!plans[i].valid) { slot=i; break; }\n TORCH_CHECK(slot >= 0, \"too many cublasLt plans\");\n Plan &p = plans[slot]; p.M=M; p.K=K; p.N=N; p.relu=relu;\n cublasLtMatmulDescCreate(&p.opDesc, CUBLAS_COMPUTE_32F, CUDA_R_32F);\n cublasOperation_t transa = CUBLAS_OP_T, transb = CUBLAS_OP_N;\n cublasLtMatmulDescSetAttribute(p.opDesc, CUBLASLT_MATMUL_DESC_TRANSA, &transa, sizeof(transa));\n cublasLtMatmulDescSetAttribute(p.opDesc, CUBLASLT_MATMUL_DESC_TRANSB, &transb, sizeof(transb));\n cublasLtEpilogue_t epi = relu ? CUBLASLT_EPILOGUE_RELU_BIAS : CUBLASLT_EPILOGUE_BIAS;\n cublasLtMatmulDescSetAttribute(p.opDesc, CUBLASLT_MATMUL_DESC_EPILOGUE, &epi, sizeof(epi));\n cublasLtMatmulDescSetAttribute(p.opDesc, CUBLASLT_MATMUL_DESC_BIAS_POINTER, &bias_ptr, sizeof(bias_ptr));\n // Column-major view of row-major tensors: C_col[N,M] = W_col[K,N]^T * X_col[K,M].\n cublasLtMatrixLayoutCreate(&p.aDesc, CUDA_R_32F, K, N, K);\n cublasLtMatrixLayoutCreate(&p.bDesc, CUDA_R_32F, K, M, K);\n cublasLtMatrixLayoutCreate(&p.cDesc, CUDA_R_32F, N, M, N);\n cublasLtMatmulPreference_t pref; cublasLtMatmulPreferenceCreate(&pref);\n cublasLtMatmulPreferenceSetAttribute(pref, CUBLASLT_MATMUL_PREF_MAX_WORKSPACE_BYTES, &workspaceSize, sizeof(workspaceSize));\n cublasLtMatmulHeuristicResult_t heur[8]; int returned = 0;\n cublasStatus_t hs = cublasLtMatmulAlgoGetHeuristic(ltHandle, p.opDesc, p.aDesc, p.bDesc, p.cDesc, p.cDesc, pref, 8, heur, &returned);\n TORCH_CHECK(hs == CUBLAS_STATUS_SUCCESS && returned > 0, \"cublasLt heuristic failed\");\n p.algo = heur[0].algo;\n cublasLtMatmulPreferenceDestroy(pref);\n p.valid = true;\n return &p;\n}\n\nstatic void lt_linear(torch::Tensor input, torch::Tensor weight, torch::Tensor bias, torch::Tensor output, bool relu, void* workspace, size_t workspaceSize) {\n int64_t M = input.size(0), K = input.size(1), N = weight.size(0);\n const void* bias_ptr_const = bias.data_ptr<float>();\n Plan* p = get_plan(M, K, N, relu, bias_ptr_const, workspaceSize);\n // Bias pointer is layer-specific; the cached descriptor is reused for layers with same sizes.\n cublasLtMatmulDescSetAttribute(p->opDesc, CUBLASLT_MATMUL_DESC_BIAS_POINTER, &bias_ptr_const, sizeof(bias_ptr_const));\n float alpha = 1.0f, beta = 0.0f;\n cublasStatus_t st = cublasLtMatmul(ltHandle, p->opDesc, &alpha,\n weight.data_ptr<float>(), p->aDesc,\n input.data_ptr<float>(), p->bDesc,\n &beta,\n output.data_ptr<float>(), p->cDesc,\n output.data_ptr<float>(), p->cDesc,\n &p->algo, workspace, workspaceSize, at::cuda::getCurrentCUDAStream());\n TORCH_CHECK(st == CUBLAS_STATUS_SUCCESS, \"cublasLtMatmul failed\");\n}\n\ntorch::Tensor mlp_forward(torch::Tensor x,\n torch::Tensor w1, torch::Tensor b1,\n torch::Tensor w2, torch::Tensor b2,\n torch::Tensor w3, torch::Tensor b3,\n torch::Tensor workspace) {\n int64_t M = x.size(0);\n auto y1 = torch::empty({M, w1.size(0)}, x.options());\n auto y2 = torch::empty({M, w2.size(0)}, x.options());\n auto y3 = torch::empty({M, w3.size(0)}, x.options());\n void* wsp = workspace.data_ptr();\n size_t wsSize = (size_t)workspace.numel();\n lt_linear(x, w1, b1, y1, true, wsp, wsSize);\n lt_linear(y1, w2, b2, y2, true, wsp, wsSize);\n lt_linear(y2, w3, b3, y3, false, wsp, wsSize);\n return y3;\n}\n'''\ncpp_source = \"torch::Tensor mlp_forward(torch::Tensor x, torch::Tensor w1, torch::Tensor b1, torch::Tensor w2, torch::Tensor b2, torch::Tensor w3, torch::Tensor b3, torch::Tensor workspace);\"\n_ext = load_inline(name='mlp_cublaslt_cached_ext_v1c', cpp_sources=cpp_source, cuda_sources=cuda_source,\n functions=['mlp_forward'], with_cuda=True,\n extra_cuda_cflags=['-O3'], extra_ldflags=['-lcublasLt','-lcublas'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, input_size, layer_sizes, output_size):\n super(ModelNew, self).__init__()\n layers = []\n current_input_size = input_size\n for layer_size in layer_sizes:\n layers.append(nn.Linear(current_input_size, layer_size))\n layers.append(nn.ReLU())\n current_input_size = layer_size\n layers.append(nn.Linear(current_input_size, output_size))\n self.network = nn.Sequential(*layers)\n self.register_buffer('_workspace', torch.empty(0, dtype=torch.uint8), persistent=False)\n def forward(self, x):\n ws = 32 * 1024 * 1024\n if self._workspace.numel() < ws or self._workspace.device != x.device:\n self._workspace = torch.empty(ws, device=x.device, dtype=torch.uint8)\n return _ext.mlp_forward(x, self.network[0].weight, self.network[0].bias,\n self.network[2].weight, self.network[2].bias,\n self.network[4].weight, self.network[4].bias,\n self._workspace)\n"
}