call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\ncpp_source = r'''\n#include <torch/extension.h>\n#include <vector>\nstd::vector<torch::Tensor> cvae_encoder(torch::Tensor x, torch::Tensor y, torch::Tensor w_enc, torch::Tensor b_enc, torch::Tensor w_mu, torch::Tensor b_mu, torch::Tensor w_lv, torch::Tensor b_lv);\nstd::vector<torch::Tensor> cvae_decoder_loss(torch::Tensor x, torch::Tensor y, torch::Tensor eps, torch::Tensor mu, torch::Tensor logvar, torch::Tensor w_dec0, torch::Tensor b_dec0, torch::Tensor w_dec2, torch::Tensor b_dec2);\n'''\n\ncuda_source = r'''\n#include <torch/extension.h>\n#include <ATen/cuda/CUDAContext.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <vector>\n#define INPUT_DIM 256\n#define LABEL_DIM 10\n#define HIDDEN_DIM 128\n#define LATENT_DIM 32\n\n__global__ void encoder_kernel(const float* __restrict__ x, const float* __restrict__ y,\n const float* __restrict__ w_enc, const float* __restrict__ b_enc,\n const float* __restrict__ w_mu, const float* __restrict__ b_mu,\n const float* __restrict__ w_lv, const float* __restrict__ b_lv,\n float* __restrict__ mu, float* __restrict__ logvar) {\n int row = blockIdx.x, tid = threadIdx.x;\n __shared__ float h[HIDDEN_DIM];\n float sum = b_enc[tid];\n const float* wx = w_enc + tid * (INPUT_DIM + LABEL_DIM);\n const float* xr = x + row * INPUT_DIM;\n #pragma unroll 4\n for (int k = 0; k < INPUT_DIM; ++k) sum += xr[k] * wx[k];\n const float* yr = y + row * LABEL_DIM;\n #pragma unroll\n for (int k = 0; k < LABEL_DIM; ++k) sum += yr[k] * wx[INPUT_DIM + k];\n h[tid] = fmaxf(sum, 0.0f);\n __syncthreads();\n if (tid < LATENT_DIM) {\n float sm = b_mu[tid], sl = b_lv[tid];\n const float* wm = w_mu + tid * HIDDEN_DIM;\n const float* wl = w_lv + tid * HIDDEN_DIM;\n #pragma unroll 4\n for (int k = 0; k < HIDDEN_DIM; ++k) { float hv = h[k]; sm += hv * wm[k]; sl += hv * wl[k]; }\n mu[row * LATENT_DIM + tid] = sm;\n logvar[row * LATENT_DIM + tid] = sl;\n }\n}\n\n__global__ void decoder_loss_kernel(const float* __restrict__ x, const float* __restrict__ y,\n const float* __restrict__ eps, const float* __restrict__ mu, const float* __restrict__ logvar,\n const float* __restrict__ w_dec0, const float* __restrict__ b_dec0,\n const float* __restrict__ w_dec2, const float* __restrict__ b_dec2,\n float* __restrict__ partial) {\n int row = blockIdx.x, tid = threadIdx.x;\n __shared__ float z[LATENT_DIM];\n __shared__ float dh[HIDDEN_DIM];\n __shared__ float red_mse[INPUT_DIM];\n __shared__ float red_kl[INPUT_DIM];\n float kl = 0.0f;\n if (tid < LATENT_DIM) {\n float m = mu[row * LATENT_DIM + tid];\n float lv = logvar[row * LATENT_DIM + tid];\n z[tid] = m + expf(0.5f * lv) * eps[row * LATENT_DIM + tid];\n kl = -0.5f * (1.0f + lv - m * m - expf(lv));\n }\n __syncthreads();\n if (tid < HIDDEN_DIM) {\n float sum = b_dec0[tid];\n const float* wd = w_dec0 + tid * (LATENT_DIM + LABEL_DIM);\n #pragma unroll\n for (int k = 0; k < LATENT_DIM; ++k) sum += z[k] * wd[k];\n const float* yr = y + row * LABEL_DIM;\n #pragma unroll\n for (int k = 0; k < LABEL_DIM; ++k) sum += yr[k] * wd[LATENT_DIM + k];\n dh[tid] = fmaxf(sum, 0.0f);\n }\n __syncthreads();\n float mse = 0.0f;\n if (tid < INPUT_DIM) {\n float sum = b_dec2[tid];\n const float* w2 = w_dec2 + tid * HIDDEN_DIM;\n #pragma unroll 4\n for (int k = 0; k < HIDDEN_DIM; ++k) sum += dh[k] * w2[k];\n float d = sum - x[row * INPUT_DIM + tid];\n mse = d * d;\n }\n red_mse[tid] = mse;\n red_kl[tid] = kl;\n __syncthreads();\n for (int offset = 128; offset > 0; offset >>= 1) {\n if (tid < offset) { red_mse[tid] += red_mse[tid + offset]; red_kl[tid] += red_kl[tid + offset]; }\n __syncthreads();\n }\n if (tid == 0) { partial[row] = red_mse[0]; partial[gridDim.x + row] = red_kl[0]; }\n}\n\n__global__ void finalize_kernel(const float* __restrict__ partial, float* __restrict__ out, int B) {\n int tid = threadIdx.x;\n __shared__ float sm[256];\n __shared__ float sk[256];\n float m = 0.0f, k = 0.0f;\n if (tid < B) { m = partial[tid]; k = partial[B + tid]; }\n sm[tid] = m; sk[tid] = k;\n __syncthreads();\n for (int off = 128; off > 0; off >>= 1) {\n if (tid < off) { sm[tid] += sm[tid+off]; sk[tid] += sk[tid+off]; }\n __syncthreads();\n }\n if (tid == 0) {\n float invB = 1.0f / (float)B;\n float recon = sm[0] * invB;\n float kl = sk[0] * invB;\n out[0] = recon + kl; out[1] = recon; out[2] = kl;\n }\n}\n\nstd::vector<torch::Tensor> cvae_encoder(torch::Tensor x, torch::Tensor y, torch::Tensor w_enc, torch::Tensor b_enc, torch::Tensor w_mu, torch::Tensor b_mu, torch::Tensor w_lv, torch::Tensor b_lv) {\n auto mu = torch::empty({x.size(0), LATENT_DIM}, x.options());\n auto logvar = torch::empty({x.size(0), LATENT_DIM}, x.options());\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n encoder_kernel<<<x.size(0), HIDDEN_DIM, 0, stream>>>(x.data_ptr<float>(), y.data_ptr<float>(), w_enc.data_ptr<float>(), b_enc.data_ptr<float>(), w_mu.data_ptr<float>(), b_mu.data_ptr<float>(), w_lv.data_ptr<float>(), b_lv.data_ptr<float>(), mu.data_ptr<float>(), logvar.data_ptr<float>());\n return {mu, logvar};\n}\nstd::vector<torch::Tensor> cvae_decoder_loss(torch::Tensor x, torch::Tensor y, torch::Tensor eps, torch::Tensor mu, torch::Tensor logvar, torch::Tensor w_dec0, torch::Tensor b_dec0, torch::Tensor w_dec2, torch::Tensor b_dec2) {\n int B = x.size(0);\n auto partial = torch::empty({2 * B}, x.options());\n auto out = torch::empty({3}, x.options());\n cudaStream_t stream = at::cuda::getCurrentCUDAStream();\n decoder_loss_kernel<<<B, INPUT_DIM, 0, stream>>>(x.data_ptr<float>(), y.data_ptr<float>(), eps.data_ptr<float>(), mu.data_ptr<float>(), logvar.data_ptr<float>(), w_dec0.data_ptr<float>(), b_dec0.data_ptr<float>(), w_dec2.data_ptr<float>(), b_dec2.data_ptr<float>(), partial.data_ptr<float>());\n finalize_kernel<<<1, 256, 0, stream>>>(partial.data_ptr<float>(), out.data_ptr<float>(), B);\n return {out.select(0,0), out.select(0,1), out.select(0,2)};\n}\n'''\n\n_ext = load_inline(name='cvae_fused_ext_v2', cpp_sources=cpp_source, cuda_sources=cuda_source,\n functions=['cvae_encoder', 'cvae_decoder_loss'], extra_cuda_cflags=['-O3','--use_fast_math'], extra_cflags=['-O3'], verbose=False)\n\nclass ModelNew(nn.Module):\n def __init__(self, input_dim, label_dim, hidden_dim, latent_dim):\n super().__init__()\n self.enc = nn.Sequential(nn.Linear(input_dim + label_dim, hidden_dim), nn.ReLU())\n self.enc_mu = nn.Linear(hidden_dim, latent_dim)\n self.enc_logvar = nn.Linear(hidden_dim, latent_dim)\n self.dec = nn.Sequential(nn.Linear(latent_dim + label_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, input_dim))\n def forward(self, x: torch.Tensor, y: torch.Tensor) -> tuple:\n enc0 = self.enc[0]\n mu, logvar = _ext.cvae_encoder(x, y, enc0.weight, enc0.bias, self.enc_mu.weight, self.enc_mu.bias, self.enc_logvar.weight, self.enc_logvar.bias)\n eps = torch.randn_like(mu)\n return tuple(_ext.cvae_decoder_loss(x, y, eps, mu, logvar, self.dec[0].weight, self.dec[0].bias, self.dec[2].weight, self.dec[2].bias))\n"
}