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 = \"\"\"\nvoid launch_compute_norms_and_concat(\n at::Tensor scalar_feat, at::Tensor vec_feat, at::Tensor combined,\n int64_t B, int64_t N, int64_t S, int64_t V);\n\nvoid launch_vector_transform(\n at::Tensor vec_feat, at::Tensor weight, at::Tensor v_out,\n int64_t B, int64_t N, int64_t V_in, int64_t V_out);\n\nvoid launch_apply_gate(\n at::Tensor v_out, at::Tensor gate,\n int64_t B, int64_t N, int64_t V_out);\n\"\"\"\n\ncuda_source = \"\"\"\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <cmath>\n\n// Fused kernel: compute vector norms and concatenate with scalar features\n__global__ void compute_norms_and_concat_kernel(\n const float* __restrict__ scalar_feat,\n const float* __restrict__ vec_feat,\n float* __restrict__ combined,\n int B, int N, int S, int V) {\n \n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int total = B * N;\n if (idx >= total) return;\n \n int b = idx / N;\n int n = idx % N;\n int base_scalar = (b * N + n) * S;\n int base_vec = (b * N + n) * V;\n int base_combined = (b * N + n) * (S + V);\n \n // Copy scalar features\n for (int s = 0; s < S; s++) {\n combined[base_combined + s] = scalar_feat[base_scalar + s];\n }\n \n // Compute norms and store\n for (int v = 0; v < V; v++) {\n float x = vec_feat[(base_vec + v) * 3 + 0];\n float y = vec_feat[(base_vec + v) * 3 + 1];\n float z = vec_feat[(base_vec + v) * 3 + 2];\n float norm = sqrtf(x*x + y*y + z*z);\n combined[base_combined + S + v] = norm;\n }\n}\n\n// Vector transform kernel: v_out = W @ v_in for each position\n__global__ void vector_transform_kernel(\n const float* __restrict__ vec_feat,\n const float* __restrict__ weight,\n float* __restrict__ v_out,\n int B, int N, int V_in, int V_out) {\n \n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int total = B * N * V_out;\n if (idx >= total) return;\n \n int vo = idx % V_out;\n int rem = idx / V_out;\n int n = rem % N;\n int b = rem / N;\n \n float sum_x = 0.0f, sum_y = 0.0f, sum_z = 0.0f;\n \n for (int vi = 0; vi < V_in; vi++) {\n float w = weight[vo * V_in + vi];\n int vec_idx = ((b * N + n) * V_in + vi) * 3;\n sum_x += w * vec_feat[vec_idx + 0];\n sum_y += w * vec_feat[vec_idx + 1];\n sum_z += w * vec_feat[vec_idx + 2];\n }\n \n int out_idx = ((b * N + n) * V_out + vo) * 3;\n v_out[out_idx + 0] = sum_x;\n v_out[out_idx + 1] = sum_y;\n v_out[out_idx + 2] = sum_z;\n}\n\n// Apply gating: v_out = gate * v_out\n__global__ void apply_gate_kernel(\n float* __restrict__ v_out,\n const float* __restrict__ gate,\n int B, int N, int V_out) {\n \n int idx = blockIdx.x * blockDim.x + threadIdx.x;\n int total = B * N * V_out * 3;\n if (idx >= total) return;\n \n int c = idx % 3;\n int rem = idx / 3;\n int vo = rem % V_out;\n rem = rem / V_out;\n int n = rem % N;\n int b = rem / N;\n \n int v_out_idx = ((b * N + n) * V_out + vo) * 3 + c;\n int gate_idx = (b * N + n) * V_out + vo;\n v_out[v_out_idx] = v_out[v_out_idx] * gate[gate_idx];\n}\n\n// C++ wrapper implementations\nvoid launch_compute_norms_and_concat(\n at::Tensor scalar_feat, at::Tensor vec_feat, at::Tensor combined,\n int64_t B, int64_t N, int64_t S, int64_t V) {\n int total = B * N;\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n compute_norms_and_concat_kernel<<<blocks, threads>>>(\n scalar_feat.data_ptr<float>(),\n vec_feat.data_ptr<float>(),\n combined.data_ptr<float>(),\n B, N, S, V);\n}\n\nvoid launch_vector_transform(\n at::Tensor vec_feat, at::Tensor weight, at::Tensor v_out,\n int64_t B, int64_t N, int64_t V_in, int64_t V_out) {\n int total = B * N * V_out;\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n vector_transform_kernel<<<blocks, threads>>>(\n vec_feat.data_ptr<float>(),\n weight.data_ptr<float>(),\n v_out.data_ptr<float>(),\n B, N, V_in, V_out);\n}\n\nvoid launch_apply_gate(\n at::Tensor v_out, at::Tensor gate,\n int64_t B, int64_t N, int64_t V_out) {\n int total = B * N * V_out * 3;\n int threads = 256;\n int blocks = (total + threads - 1) / threads;\n apply_gate_kernel<<<blocks, threads>>>(\n v_out.data_ptr<float>(),\n gate.data_ptr<float>(),\n B, N, V_out);\n}\n\"\"\"\n\nse3_ops = load_inline(\n name='se3_ops_v3',\n cpp_sources=cpp_source,\n cuda_sources=cuda_source,\n functions=['launch_compute_norms_and_concat', 'launch_vector_transform', 'launch_apply_gate'],\n extra_cuda_cflags=['-O3'],\n)\n\nclass ModelNew(nn.Module):\n def __init__(self, scalar_in, scalar_out, vector_in, vector_out):\n super().__init__()\n self.scalar_in = scalar_in\n self.scalar_out = scalar_out\n self.vector_in = vector_in\n self.vector_out = vector_out\n \n self.scalar_linear_weight = nn.Parameter(torch.randn(scalar_out, scalar_in + vector_in))\n self.scalar_linear_bias = nn.Parameter(torch.zeros(scalar_out))\n nn.init.xavier_uniform_(self.scalar_linear_weight)\n \n self.vector_weight = nn.Parameter(torch.randn(vector_out, vector_in))\n nn.init.xavier_uniform_(self.vector_weight)\n \n self.vector_gate_weight = nn.Parameter(torch.randn(vector_out, scalar_in + vector_in))\n self.vector_gate_bias = nn.Parameter(torch.zeros(vector_out))\n nn.init.xavier_uniform_(self.vector_gate_weight)\n \n def forward(self, scalar_feat: torch.Tensor, vector_feat: torch.Tensor) -> tuple:\n B, N, S = scalar_feat.shape\n _, _, V, _ = vector_feat.shape\n \n # Ensure contiguous\n scalar_feat = scalar_feat.contiguous()\n vector_feat = vector_feat.contiguous()\n \n # Allocate combined tensor\n combined = torch.empty(B, N, S + V, device=scalar_feat.device, dtype=scalar_feat.dtype)\n \n # Compute norms and concatenate\n se3_ops.launch_compute_norms_and_concat(\n scalar_feat, vector_feat, combined, B, N, S, V)\n \n # Scalar linear output\n combined_flat = combined.view(-1, S + V)\n s_out_flat = torch.nn.functional.linear(combined_flat, self.scalar_linear_weight, self.scalar_linear_bias)\n s_out = s_out_flat.view(B, N, -1)\n \n # Vector transform\n v_out = torch.empty(B, N, self.vector_out, 3, device=vector_feat.device, dtype=vector_feat.dtype)\n se3_ops.launch_vector_transform(\n vector_feat, self.vector_weight, v_out, B, N, V, self.vector_out)\n \n # Gate computation\n gate_pre = torch.nn.functional.linear(combined_flat, self.vector_gate_weight, self.vector_gate_bias)\n gate_flat = torch.sigmoid(gate_pre)\n gate = gate_flat.view(B, N, self.vector_out)\n \n # Apply gate\n se3_ops.launch_apply_gate(v_out, gate, B, N, self.vector_out)\n \n return s_out, v_out"
}