correct
47_virtual_all_gather_concat_linear.py
started
2026-05-02T18:38:42Z
timingkernelbench.timing
kernel mean / median / std
0.01 / — / 1.33e-04 μs
ref mean / median / std
0.01 / — / 6.67e-04 μs
numerical precisioneval_kernel_against_ref
gpu memoryextended_metrics.measure_memory
kernel launches / fusiontorch.profiler
fusion ratio (ref / kernel)
14.00x
SOL (speed-of-light)nsight_hardware_counters
roofline / occupancynsight_hardware_counters
warp stalls (top 5)nsight
reference PyTorch source (the prompt the agent sees)
"""
Virtual all-gather on the last dim: stack R tensors of shape (B, H) into (B, R*H), then Linear.
"""
import torch
import torch.nn as nn
from kernelbench.distributed_collectives import default_device
R = 4
B = 12
H = 32
K = 56
class Model(nn.Module):
def __init__(self):
super().__init__()
self.proj = nn.Linear(R * H, K, bias=True)
def forward(self, x: torch.Tensor) -> torch.Tensor:
r, b, h = x.shape
assert r == R and h == H
parts = [x[i] for i in range(R)]
gathered = torch.cat(parts, dim=-1)
return self.proj(gathered)
def get_inputs():
dev = default_device()
p = popcorn_pri
return [torch.randn(p.jitter_int(R), p.jitter_int(B), p.jitter_int(D, align=8), device=dev)]
def get_init_inputs():
return []
turn 016.3s turn · 16.3s LLM · 0.0s tools
reasoning
**Calculating thread efficiencies**
I'm considering a block-per-row approach for computations with threads. So, if I have 128 threads per block and I'm using B=12, I might have each thread compute outputs for K. For each K, I need to reduce across those 128 threads. An alternative is to use 256 threads per block, but that might complicate my loading processes. It's getting a bit heavy on overhead; I wonder if launching everything in one kernel could streamline this?
**Exploring block configurations**
I'm thinking about using one block for each combination of (b, group k). This would give me 12x56 blocks, with one warp per output. It could increase parallelism, but I'm concerned that the block launch overhead will remain the same since the scheduler handles many blocks. The workload seems relatively small, but having a warp per output might help structure my blocks better. I’m exploring if this approach can be effective for my processing needs.
call → get_gpu_specs
callget_gpu_specs
{}
result ← get_gpu_specs (ok)
okget_gpu_specs
GPU specs for NVIDIA H100 80GB HBM3:
total memory (runtime): 79.1 GB
spec entry: H100
GPU Architecture: Hopper
GPU Memory: 80GB
Memory Bandwidth: 3.35 TB/s
FP64 TFLOPS: 34
FP64 Tensor Core TFLOPS: 67
FP32 TFLOPS: 67
TF32 Tensor Core TFLOPS: 989 with sparsity
BFLOAT16 Tensore Core TFLOPS: 1979 with sparsity
FP16 Tensor Core TFLOPS: 1979 with sparsity
FP8 Tensor Core TFLOPS: 3958 with sparsity
INT8 Tensor Core TOPS: 3958 with sparsity
Register File Size: 64K 32-bit registers per SM
Maximum number of registers per thread: 255
Maximum number of thread blocks per SM: 32
Shared memory capacity per SM: 228 KB
Maximum shared memory per thread block: 227 KB
turn 1 · 1 tool call(s) · 13.1s turn · 13.1s LLM · 7,012 chars (click to expand)
turn 113.1s turn · 13.1s LLM · 0.0s tools
reasoning
**Evaluating CUDA compilation**
I'm considering the optimal approach for warp execution with 4 FMAs to maximize performance. It seems I'll need to manage weight loads and segments effectively. The aim is to achieve a precision difference of likely within 1e-4 between implementations. Using __ldg might enhance performance, and I’ll think about compiling with specific function declarations in C++ without relying on pybind. I also want to ensure I include the necessary optimization flags and compile checks. Let’s get started on this!
call → compile_kernel
callcompile_kernel
{
"kernel_code": "import torch\nimport torch.nn as nn\nfrom torch.utils.cpp_extension import load_inline\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#ifndef CHECK_CUDA\n#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be a CUDA tensor\")\n#endif\n\nconstexpr int R_ = 4;\nconstexpr int B_ = 12;\nconstexpr int H_ = 32;\nconstexpr int K_ = 56;\nconstexpr int N_ = R_ * H_;\nconstexpr int WARPS_PER_BLOCK = 8;\n\n__global__ __launch_bounds__(WARPS_PER_BLOCK * 32, 4)\nvoid vag_linear_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ y) {\n int b = blockIdx.x;\n int k = blockIdx.y * WARPS_PER_BLOCK + (threadIdx.x >> 5);\n int lane = threadIdx.x & 31;\n\n if (k >= K_) return;\n\n float sum = 0.0f;\n#pragma unroll\n for (int rr = 0; rr < R_; ++rr) {\n int n = rr * H_ + lane;\n float xv = x[(rr * B_ + b) * H_ + lane];\n float wv = w[k * N_ + n];\n sum = fmaf(xv, wv, sum);\n }\n\n#pragma unroll\n for (int offset = 16; offset > 0; offset >>= 1) {\n sum += __shfl_down_sync(0xffffffff, sum, offset);\n }\n if (lane == 0) {\n y[b * K_ + k] = sum + bias[k];\n }\n}\n\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n CHECK_CUDA(x); CHECK_CUDA(weight); CHECK_CUDA(bias);\n TORCH_CHECK(x.scalar_type() == torch::kFloat32, \"x must be float32\");\n TORCH_CHECK(weight.scalar_type() == torch::kFloat32, \"weight must be float32\");\n TORCH_CHECK(bias.scalar_type() == torch::kFloat32, \"bias must be float32\");\n auto y = torch::empty({B_, K_}, x.options());\n dim3 block(WARPS_PER_BLOCK * 32);\n dim3 grid(B_, (K_ + WARPS_PER_BLOCK - 1) / WARPS_PER_BLOCK);\n vag_linear_kernel<<<grid, block>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>());\n return y;\n}\n'''\n\n_ext = load_inline(\n name='vag_linear_ext_v1',\n cpp_sources='',\n cuda_sources=_cuda_src,\n functions=['vag_linear_forward'],\n extra_cuda_cflags=['-O3', '--use_fast_math'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.proj = nn.Linear(4 * 32, 56, bias=True)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return _ext.vag_linear_forward(x, self.proj.weight, self.proj.bias)\n"
}
result ← compile_kernel (fail)
failcompile_kernel
compile_kernel FAILED: RuntimeError.
RuntimeError: Error building extension 'vag_linear_ext_v1': [1/3] /opt/conda/bin/x86_64-conda-linux-gnu-c++ -MMD -MF main.o.d -DTORCH_EXTENSION_NAME=vag_linear_ext_v1 -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /home/prabhune/.local/share/uv/python/cpython-3.10-linux-x86_64-gnu/include/python3.10 -fPIC -std=c++17 -c /scratch/tejas/PopcornBench/runs/l12_default/popcorn/gpt-5.5-priority/level_2_problem_47_cache/k_9c7abb74ef9f/vag_linear_ext_v1/main.cpp -o main.o
FAILED: [code=1] main.o
/opt/conda/bin/x86_64-conda-linux-gnu-c++ -MMD -MF main.o.d -DTORCH_EXTENSION_NAME=vag_linear_ext_v1 -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /home/prabhune/.local/share/uv/python/cpython-3.10-linux-x86_64-gnu/include/python3.10 -fPIC -std=c++17 -c /scratch/tejas/PopcornBench/runs/l12_default/popcorn/gpt-5.5-priority/level_2_problem_47_cache/k_9c7abb74ef9f/vag_linear_ext_v1/main.cpp -o main.o
/scratch/tejas/PopcornBench/runs/l12_default/popcorn/gpt-5.5-priority/level_2_problem_47_cache/k_9c7abb74ef9f/vag_linear_ext_v1/main.cpp: In function 'void pybind11_init_vag_linear_ext_v1(pybind11::module_&)':
/scratch/tejas/PopcornBench/runs/l12_default/popcorn/gpt-5.5-priority/level_2_problem_47_cache/k_9c7abb74ef9f/vag_linear_ext_v1/main.cpp:4:57: error: 'vag_linear_forward' was not declared in this scope
4 | m.def("vag_linear_forward", torch::wrap_pybind_function(vag_linear_forward), "vag_linear_forward");
| ^~~~~~~~~~~~~~~~~~
[2/3] /usr/local/cuda/bin/nvcc -MD -MF cuda.cuda.o.d -ccbin /opt/conda/bin/x86_64-conda-linux-gnu-cc -DTORCH_EXTENSION_NAME=vag_linear_ext_v1 -DTORCH_API_INCLUDE_EXTENSION_H -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include -isystem /scratch/tejas/PopcornBench/.venv/lib/python3.10/site-packages/torch/include/torch/csrc/api/include -isystem /usr/local/cuda/include -isystem /home/prabhune/.local/share/uv/python/cpython-3.10-linux-x86_64-gnu/include/python3.10 -D__CUDA_NO_HALF_OPERATORS__ -D__CUDA_NO_HALF_CONVERSIONS__ -D__CUDA_NO_BFLOAT16_CONVERSIONS__ -D__CUDA_NO_HALF2_OPERATORS__ --expt-relaxed-constexpr -gencode=arch=compute_90,code=compute_90 -gencode=arch=compute_90,code=sm_90 --compiler-options '-fPIC' -O3 --use_fast_math -std=c++17 -c /scratch/tejas/PopcornBench/runs/l12_default/popcorn/gpt-5.5-priority/level_2_problem_47_cache/k_9c7abb74ef9f/vag_linear_ext_v1/cuda.cu -o cuda.cuda.o
nvcc warning : incompatible redefinition for option 'compiler-bindir', the last value of this option was used
ninja: build stopped: subcommand failed.
turn 26.3s turn · 6.3s LLM · 0.0s tools
reasoning
**Declaring tensor function**
I need to declare a function in the cpp_sources. It's something like `torch::Tensor vag_linear_forward(...)` that I need to provide. After that, I should compile it to ensure it works correctly. I'm wondering if I've considered all the necessary parameters in the function declaration. Once I have it declared and compiled, I'll know I'm on the right path. Let's get this sorted out properly!
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>\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be a CUDA tensor\")\n\nconstexpr int R_ = 4;\nconstexpr int B_ = 12;\nconstexpr int H_ = 32;\nconstexpr int K_ = 56;\nconstexpr int N_ = R_ * H_;\nconstexpr int WARPS_PER_BLOCK = 8;\n\n__global__ __launch_bounds__(WARPS_PER_BLOCK * 32, 4)\nvoid vag_linear_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ y) {\n int b = blockIdx.x;\n int k = blockIdx.y * WARPS_PER_BLOCK + (threadIdx.x >> 5);\n int lane = threadIdx.x & 31;\n if (k >= K_) return;\n float sum = 0.0f;\n#pragma unroll\n for (int rr = 0; rr < R_; ++rr) {\n int n = rr * H_ + lane;\n sum = fmaf(x[(rr * B_ + b) * H_ + lane], w[k * N_ + n], sum);\n }\n#pragma unroll\n for (int offset = 16; offset > 0; offset >>= 1) {\n sum += __shfl_down_sync(0xffffffff, sum, offset);\n }\n if (lane == 0) y[b * K_ + k] = sum + bias[k];\n}\n\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n CHECK_CUDA(x); CHECK_CUDA(weight); CHECK_CUDA(bias);\n auto y = torch::empty({B_, K_}, x.options());\n dim3 block(WARPS_PER_BLOCK * 32);\n dim3 grid(B_, (K_ + WARPS_PER_BLOCK - 1) / WARPS_PER_BLOCK);\n vag_linear_kernel<<<grid, block>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>());\n return y;\n}\n'''\n\n_ext = load_inline(\n name='vag_linear_ext_v2',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['vag_linear_forward'],\n extra_cuda_cflags=['-O3', '--use_fast_math'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.proj = nn.Linear(4 * 32, 56, bias=True)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return _ext.vag_linear_forward(x, self.proj.weight, self.proj.bias)\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 35.7s turn · 5.7s LLM · 0.0s tools
call → run_correctness
callrun_correctness
{
"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>\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be a CUDA tensor\")\n\nconstexpr int R_ = 4;\nconstexpr int B_ = 12;\nconstexpr int H_ = 32;\nconstexpr int K_ = 56;\nconstexpr int N_ = R_ * H_;\nconstexpr int WARPS_PER_BLOCK = 8;\n\n__global__ __launch_bounds__(WARPS_PER_BLOCK * 32, 4)\nvoid vag_linear_kernel(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ y) {\n int b = blockIdx.x;\n int k = blockIdx.y * WARPS_PER_BLOCK + (threadIdx.x >> 5);\n int lane = threadIdx.x & 31;\n if (k >= K_) return;\n float sum = 0.0f;\n#pragma unroll\n for (int rr = 0; rr < R_; ++rr) {\n int n = rr * H_ + lane;\n sum = fmaf(x[(rr * B_ + b) * H_ + lane], w[k * N_ + n], sum);\n }\n#pragma unroll\n for (int offset = 16; offset > 0; offset >>= 1) {\n sum += __shfl_down_sync(0xffffffff, sum, offset);\n }\n if (lane == 0) y[b * K_ + k] = sum + bias[k];\n}\n\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n CHECK_CUDA(x); CHECK_CUDA(weight); CHECK_CUDA(bias);\n auto y = torch::empty({B_, K_}, x.options());\n dim3 block(WARPS_PER_BLOCK * 32);\n dim3 grid(B_, (K_ + WARPS_PER_BLOCK - 1) / WARPS_PER_BLOCK);\n vag_linear_kernel<<<grid, block>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>());\n return y;\n}\n'''\n\n_ext = load_inline(\n name='vag_linear_ext_v2',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['vag_linear_forward'],\n extra_cuda_cflags=['-O3', '--use_fast_math'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.proj = nn.Linear(4 * 32, 56, bias=True)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return _ext.vag_linear_forward(x, self.proj.weight, self.proj.bias)\n"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=2.38e-07 mean_abs_err=4.59e-08 max_rel_err=3.49e-05
turn 418.6s turn · 18.6s LLM · 0.0s tools
reasoning
**Optimizing kernel execution**
I need to optimize the timing since submitting gives a runtime but then just ends. I can only test the final variant without timing, so I might infer some results. There's a thought to use correctness instead of timing. The kernel launch time dominates, likely at 3-5us. Fine-tuning the number of blocks could help; maybe by reducing to one block per configuration, I can see if that speeds it up. I need to decide on the best approach.
**Optimizing output computation**
Each block computes 56 outputs sequentially, with 128 threads involved, where each thread performs one product. The reduction from 128 to 7 involves shuffling across multiple warps, which isn't straightforward. There's a possibility of using a warp per k, currently set at 8 warps, with 7 blocks per configuration. Maybe grouping rows could simplify things. If one warp computes for two k values, I can reduce the number of blocks and warps and streamline data loads, enabling more efficient sums and storage of multiple outputs.
**Configuring block and warp settings**
Each block has 8 warps, leading to 32k outputs per block. The grid's y dimension is set to 2 per block, which means 24 blocks total. The number of warps is 192 versus 672. The workload remains the same at 56*128, but with lower x loads, it allows for more registers and faster performance. I'm thinking of implementing a system where one warp computes 4 consecutive k values, with K_TILE set to 4. This arrangement ensures there are 8 warps per block, resulting in 32 outputs.
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>\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be a CUDA tensor\")\n\nconstexpr int R_ = 4;\nconstexpr int B_ = 12;\nconstexpr int H_ = 32;\nconstexpr int K_ = 56;\nconstexpr int N_ = R_ * H_;\nconstexpr int WARPS_PER_BLOCK = 8;\nconstexpr int KTILE = 4;\nconstexpr int K_PER_BLOCK = WARPS_PER_BLOCK * KTILE;\n\n__global__ __launch_bounds__(WARPS_PER_BLOCK * 32, 4)\nvoid vag_linear_kernel4(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ y) {\n int b = blockIdx.x;\n int warp = threadIdx.x >> 5;\n int lane = threadIdx.x & 31;\n int k0 = blockIdx.y * K_PER_BLOCK + warp * KTILE;\n\n float s0 = 0.0f, s1 = 0.0f, s2 = 0.0f, s3 = 0.0f;\n#pragma unroll\n for (int rr = 0; rr < R_; ++rr) {\n int n = rr * H_ + lane;\n float xv = x[(rr * B_ + b) * H_ + lane];\n const float* wp = w + k0 * N_ + n;\n if (k0 + 0 < K_) s0 = fmaf(xv, wp[0 * N_], s0);\n if (k0 + 1 < K_) s1 = fmaf(xv, wp[1 * N_], s1);\n if (k0 + 2 < K_) s2 = fmaf(xv, wp[2 * N_], s2);\n if (k0 + 3 < K_) s3 = fmaf(xv, wp[3 * N_], s3);\n }\n#pragma unroll\n for (int off = 16; off > 0; off >>= 1) {\n s0 += __shfl_down_sync(0xffffffff, s0, off);\n s1 += __shfl_down_sync(0xffffffff, s1, off);\n s2 += __shfl_down_sync(0xffffffff, s2, off);\n s3 += __shfl_down_sync(0xffffffff, s3, off);\n }\n if (lane == 0) {\n if (k0 + 0 < K_) y[b * K_ + k0 + 0] = s0 + bias[k0 + 0];\n if (k0 + 1 < K_) y[b * K_ + k0 + 1] = s1 + bias[k0 + 1];\n if (k0 + 2 < K_) y[b * K_ + k0 + 2] = s2 + bias[k0 + 2];\n if (k0 + 3 < K_) y[b * K_ + k0 + 3] = s3 + bias[k0 + 3];\n }\n}\n\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n CHECK_CUDA(x); CHECK_CUDA(weight); CHECK_CUDA(bias);\n auto y = torch::empty({B_, K_}, x.options());\n dim3 block(WARPS_PER_BLOCK * 32);\n dim3 grid(B_, (K_ + K_PER_BLOCK - 1) / K_PER_BLOCK);\n vag_linear_kernel4<<<grid, block>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>());\n return y;\n}\n'''\n\n_ext = load_inline(\n name='vag_linear_ext_v3',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['vag_linear_forward'],\n extra_cuda_cflags=['-O3', '--use_fast_math'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.proj = nn.Linear(4 * 32, 56, bias=True)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return _ext.vag_linear_forward(x, self.proj.weight, self.proj.bias)\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 57.0s turn · 7.0s LLM · 0.0s tools
call → run_correctness
callrun_correctness
{
"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>\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x \" must be a CUDA tensor\")\n\nconstexpr int R_ = 4;\nconstexpr int B_ = 12;\nconstexpr int H_ = 32;\nconstexpr int K_ = 56;\nconstexpr int N_ = R_ * H_;\nconstexpr int WARPS_PER_BLOCK = 8;\nconstexpr int KTILE = 4;\nconstexpr int K_PER_BLOCK = WARPS_PER_BLOCK * KTILE;\n\n__global__ __launch_bounds__(WARPS_PER_BLOCK * 32, 4)\nvoid vag_linear_kernel4(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ y) {\n int b = blockIdx.x;\n int warp = threadIdx.x >> 5;\n int lane = threadIdx.x & 31;\n int k0 = blockIdx.y * K_PER_BLOCK + warp * KTILE;\n\n float s0 = 0.0f, s1 = 0.0f, s2 = 0.0f, s3 = 0.0f;\n#pragma unroll\n for (int rr = 0; rr < R_; ++rr) {\n int n = rr * H_ + lane;\n float xv = x[(rr * B_ + b) * H_ + lane];\n const float* wp = w + k0 * N_ + n;\n if (k0 + 0 < K_) s0 = fmaf(xv, wp[0 * N_], s0);\n if (k0 + 1 < K_) s1 = fmaf(xv, wp[1 * N_], s1);\n if (k0 + 2 < K_) s2 = fmaf(xv, wp[2 * N_], s2);\n if (k0 + 3 < K_) s3 = fmaf(xv, wp[3 * N_], s3);\n }\n#pragma unroll\n for (int off = 16; off > 0; off >>= 1) {\n s0 += __shfl_down_sync(0xffffffff, s0, off);\n s1 += __shfl_down_sync(0xffffffff, s1, off);\n s2 += __shfl_down_sync(0xffffffff, s2, off);\n s3 += __shfl_down_sync(0xffffffff, s3, off);\n }\n if (lane == 0) {\n if (k0 + 0 < K_) y[b * K_ + k0 + 0] = s0 + bias[k0 + 0];\n if (k0 + 1 < K_) y[b * K_ + k0 + 1] = s1 + bias[k0 + 1];\n if (k0 + 2 < K_) y[b * K_ + k0 + 2] = s2 + bias[k0 + 2];\n if (k0 + 3 < K_) y[b * K_ + k0 + 3] = s3 + bias[k0 + 3];\n }\n}\n\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n CHECK_CUDA(x); CHECK_CUDA(weight); CHECK_CUDA(bias);\n auto y = torch::empty({B_, K_}, x.options());\n dim3 block(WARPS_PER_BLOCK * 32);\n dim3 grid(B_, (K_ + K_PER_BLOCK - 1) / K_PER_BLOCK);\n vag_linear_kernel4<<<grid, block>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>());\n return y;\n}\n'''\n\n_ext = load_inline(\n name='vag_linear_ext_v3',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['vag_linear_forward'],\n extra_cuda_cflags=['-O3', '--use_fast_math'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.proj = nn.Linear(4 * 32, 56, bias=True)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return _ext.vag_linear_forward(x, self.proj.weight, self.proj.bias)\n"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=2.38e-07 mean_abs_err=4.59e-08 max_rel_err=3.49e-05
turn 629.6s turn · 29.6s LLM · 0.0s tools
reasoning
**Evaluating CPU overhead**
I’m considering the CPU overhead from using pybind. It seems fine to implement KTILE8 without checks for now. I want to make sure that correctness is maintained, but skipping those checks might help with performance. I’m curious if this approach will ultimately affect the efficiency of my implementation, or if it’ll lead to any unforeseen errors down the line. Balancing performance and correctness can be tricky, but I’ll keep my focus on getting it right!
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>\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\nconstexpr int R_ = 4;\nconstexpr int B_ = 12;\nconstexpr int H_ = 32;\nconstexpr int K_ = 56;\nconstexpr int N_ = R_ * H_;\nconstexpr int WARPS_PER_BLOCK = 7;\nconstexpr int KTILE = 8;\n\n__global__ __launch_bounds__(WARPS_PER_BLOCK * 32, 4)\nvoid vag_linear_kernel8(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ y) {\n int b = blockIdx.x;\n int warp = threadIdx.x >> 5;\n int lane = threadIdx.x & 31;\n int k0 = warp * KTILE;\n\n float s0=0.0f, s1=0.0f, s2=0.0f, s3=0.0f;\n float s4=0.0f, s5=0.0f, s6=0.0f, s7=0.0f;\n#pragma unroll\n for (int rr = 0; rr < R_; ++rr) {\n int n = rr * H_ + lane;\n float xv = x[(rr * B_ + b) * H_ + lane];\n const float* wp = w + k0 * N_ + n;\n s0 = fmaf(xv, wp[0 * N_], s0);\n s1 = fmaf(xv, wp[1 * N_], s1);\n s2 = fmaf(xv, wp[2 * N_], s2);\n s3 = fmaf(xv, wp[3 * N_], s3);\n s4 = fmaf(xv, wp[4 * N_], s4);\n s5 = fmaf(xv, wp[5 * N_], s5);\n s6 = fmaf(xv, wp[6 * N_], s6);\n s7 = fmaf(xv, wp[7 * N_], s7);\n }\n#pragma unroll\n for (int off = 16; off > 0; off >>= 1) {\n s0 += __shfl_down_sync(0xffffffff, s0, off);\n s1 += __shfl_down_sync(0xffffffff, s1, off);\n s2 += __shfl_down_sync(0xffffffff, s2, off);\n s3 += __shfl_down_sync(0xffffffff, s3, off);\n s4 += __shfl_down_sync(0xffffffff, s4, off);\n s5 += __shfl_down_sync(0xffffffff, s5, off);\n s6 += __shfl_down_sync(0xffffffff, s6, off);\n s7 += __shfl_down_sync(0xffffffff, s7, off);\n }\n if (lane == 0) {\n float* yp = y + b * K_ + k0;\n const float* bp = bias + k0;\n yp[0] = s0 + bp[0];\n yp[1] = s1 + bp[1];\n yp[2] = s2 + bp[2];\n yp[3] = s3 + bp[3];\n yp[4] = s4 + bp[4];\n yp[5] = s5 + bp[5];\n yp[6] = s6 + bp[6];\n yp[7] = s7 + bp[7];\n }\n}\n\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n auto y = torch::empty({B_, K_}, x.options());\n vag_linear_kernel8<<<B_, WARPS_PER_BLOCK * 32>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>());\n return y;\n}\n'''\n\n_ext = load_inline(\n name='vag_linear_ext_v4',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['vag_linear_forward'],\n extra_cuda_cflags=['-O3', '--use_fast_math'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.proj = nn.Linear(4 * 32, 56, bias=True)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return _ext.vag_linear_forward(x, self.proj.weight, self.proj.bias)\n"
}
result ← compile_kernel (ok)
okcompile_kernel
compile_kernel PASSED: kernel compiled without errors.
turn 78.5s turn · 8.5s LLM · 0.0s tools
call → run_correctness
callrun_correctness
{
"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>\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\nconstexpr int R_ = 4;\nconstexpr int B_ = 12;\nconstexpr int H_ = 32;\nconstexpr int K_ = 56;\nconstexpr int N_ = R_ * H_;\nconstexpr int WARPS_PER_BLOCK = 7;\nconstexpr int KTILE = 8;\n\n__global__ __launch_bounds__(WARPS_PER_BLOCK * 32, 4)\nvoid vag_linear_kernel8(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ y) {\n int b = blockIdx.x;\n int warp = threadIdx.x >> 5;\n int lane = threadIdx.x & 31;\n int k0 = warp * KTILE;\n\n float s0=0.0f, s1=0.0f, s2=0.0f, s3=0.0f;\n float s4=0.0f, s5=0.0f, s6=0.0f, s7=0.0f;\n#pragma unroll\n for (int rr = 0; rr < R_; ++rr) {\n int n = rr * H_ + lane;\n float xv = x[(rr * B_ + b) * H_ + lane];\n const float* wp = w + k0 * N_ + n;\n s0 = fmaf(xv, wp[0 * N_], s0);\n s1 = fmaf(xv, wp[1 * N_], s1);\n s2 = fmaf(xv, wp[2 * N_], s2);\n s3 = fmaf(xv, wp[3 * N_], s3);\n s4 = fmaf(xv, wp[4 * N_], s4);\n s5 = fmaf(xv, wp[5 * N_], s5);\n s6 = fmaf(xv, wp[6 * N_], s6);\n s7 = fmaf(xv, wp[7 * N_], s7);\n }\n#pragma unroll\n for (int off = 16; off > 0; off >>= 1) {\n s0 += __shfl_down_sync(0xffffffff, s0, off);\n s1 += __shfl_down_sync(0xffffffff, s1, off);\n s2 += __shfl_down_sync(0xffffffff, s2, off);\n s3 += __shfl_down_sync(0xffffffff, s3, off);\n s4 += __shfl_down_sync(0xffffffff, s4, off);\n s5 += __shfl_down_sync(0xffffffff, s5, off);\n s6 += __shfl_down_sync(0xffffffff, s6, off);\n s7 += __shfl_down_sync(0xffffffff, s7, off);\n }\n if (lane == 0) {\n float* yp = y + b * K_ + k0;\n const float* bp = bias + k0;\n yp[0] = s0 + bp[0];\n yp[1] = s1 + bp[1];\n yp[2] = s2 + bp[2];\n yp[3] = s3 + bp[3];\n yp[4] = s4 + bp[4];\n yp[5] = s5 + bp[5];\n yp[6] = s6 + bp[6];\n yp[7] = s7 + bp[7];\n }\n}\n\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n auto y = torch::empty({B_, K_}, x.options());\n vag_linear_kernel8<<<B_, WARPS_PER_BLOCK * 32>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>());\n return y;\n}\n'''\n\n_ext = load_inline(\n name='vag_linear_ext_v4',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['vag_linear_forward'],\n extra_cuda_cflags=['-O3', '--use_fast_math'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.proj = nn.Linear(4 * 32, 56, bias=True)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return _ext.vag_linear_forward(x, self.proj.weight, self.proj.bias)\n"
}
result ← run_correctness (ok)
okrun_correctness
run_correctness PASSED: (5 / 5) trials all matched the reference.
Numerical precision: max_abs_err=2.38e-07 mean_abs_err=4.59e-08 max_rel_err=3.49e-05
turn 88.3s turn · 8.3s LLM · 0.0s tools
reasoning
**Considering submission strategy**
I need to submit, but it makes sense to do a static check first. I’ve identified 22 tool calls that seem okay, so I could submit v4. However, I need to consider speed since kernel launch overhead can dominate. The PyTorch cat+linear is likely using multiple kernels, while our single kernel is faster. Maybe optimizing with torch.empty overhead could help too. I could make it persistent. I think I should run a static check before finalizing the submission.
call → static_check
callstatic_check
{
"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>\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\nconstexpr int R_ = 4;\nconstexpr int B_ = 12;\nconstexpr int H_ = 32;\nconstexpr int K_ = 56;\nconstexpr int N_ = R_ * H_;\nconstexpr int WARPS_PER_BLOCK = 7;\nconstexpr int KTILE = 8;\n\n__global__ __launch_bounds__(WARPS_PER_BLOCK * 32, 4)\nvoid vag_linear_kernel8(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ y) {\n int b = blockIdx.x;\n int warp = threadIdx.x >> 5;\n int lane = threadIdx.x & 31;\n int k0 = warp * KTILE;\n\n float s0=0.0f, s1=0.0f, s2=0.0f, s3=0.0f;\n float s4=0.0f, s5=0.0f, s6=0.0f, s7=0.0f;\n#pragma unroll\n for (int rr = 0; rr < R_; ++rr) {\n int n = rr * H_ + lane;\n float xv = x[(rr * B_ + b) * H_ + lane];\n const float* wp = w + k0 * N_ + n;\n s0 = fmaf(xv, wp[0 * N_], s0);\n s1 = fmaf(xv, wp[1 * N_], s1);\n s2 = fmaf(xv, wp[2 * N_], s2);\n s3 = fmaf(xv, wp[3 * N_], s3);\n s4 = fmaf(xv, wp[4 * N_], s4);\n s5 = fmaf(xv, wp[5 * N_], s5);\n s6 = fmaf(xv, wp[6 * N_], s6);\n s7 = fmaf(xv, wp[7 * N_], s7);\n }\n#pragma unroll\n for (int off = 16; off > 0; off >>= 1) {\n s0 += __shfl_down_sync(0xffffffff, s0, off);\n s1 += __shfl_down_sync(0xffffffff, s1, off);\n s2 += __shfl_down_sync(0xffffffff, s2, off);\n s3 += __shfl_down_sync(0xffffffff, s3, off);\n s4 += __shfl_down_sync(0xffffffff, s4, off);\n s5 += __shfl_down_sync(0xffffffff, s5, off);\n s6 += __shfl_down_sync(0xffffffff, s6, off);\n s7 += __shfl_down_sync(0xffffffff, s7, off);\n }\n if (lane == 0) {\n float* yp = y + b * K_ + k0;\n const float* bp = bias + k0;\n yp[0] = s0 + bp[0];\n yp[1] = s1 + bp[1];\n yp[2] = s2 + bp[2];\n yp[3] = s3 + bp[3];\n yp[4] = s4 + bp[4];\n yp[5] = s5 + bp[5];\n yp[6] = s6 + bp[6];\n yp[7] = s7 + bp[7];\n }\n}\n\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n auto y = torch::empty({B_, K_}, x.options());\n vag_linear_kernel8<<<B_, WARPS_PER_BLOCK * 32>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>());\n return y;\n}\n'''\n\n_ext = load_inline(\n name='vag_linear_ext_v4',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['vag_linear_forward'],\n extra_cuda_cflags=['-O3', '--use_fast_math'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.proj = nn.Linear(4 * 32, 56, bias=True)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return _ext.vag_linear_forward(x, self.proj.weight, self.proj.bias)\n"
}
result ← static_check (ok)
okstatic_check
static_check PASSED: no violations or warnings detected.
turn 97.9s turn · 7.9s LLM · 0.0s tools · FINAL
call → submit_kernel
callsubmit_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>\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);\n'''\n\n_cuda_src = r'''\n#include <torch/extension.h>\n#include <cuda.h>\n#include <cuda_runtime.h>\n\nconstexpr int R_ = 4;\nconstexpr int B_ = 12;\nconstexpr int H_ = 32;\nconstexpr int K_ = 56;\nconstexpr int N_ = R_ * H_;\nconstexpr int WARPS_PER_BLOCK = 7;\nconstexpr int KTILE = 8;\n\n__global__ __launch_bounds__(WARPS_PER_BLOCK * 32, 4)\nvoid vag_linear_kernel8(const float* __restrict__ x,\n const float* __restrict__ w,\n const float* __restrict__ bias,\n float* __restrict__ y) {\n int b = blockIdx.x;\n int warp = threadIdx.x >> 5;\n int lane = threadIdx.x & 31;\n int k0 = warp * KTILE;\n\n float s0=0.0f, s1=0.0f, s2=0.0f, s3=0.0f;\n float s4=0.0f, s5=0.0f, s6=0.0f, s7=0.0f;\n#pragma unroll\n for (int rr = 0; rr < R_; ++rr) {\n int n = rr * H_ + lane;\n float xv = x[(rr * B_ + b) * H_ + lane];\n const float* wp = w + k0 * N_ + n;\n s0 = fmaf(xv, wp[0 * N_], s0);\n s1 = fmaf(xv, wp[1 * N_], s1);\n s2 = fmaf(xv, wp[2 * N_], s2);\n s3 = fmaf(xv, wp[3 * N_], s3);\n s4 = fmaf(xv, wp[4 * N_], s4);\n s5 = fmaf(xv, wp[5 * N_], s5);\n s6 = fmaf(xv, wp[6 * N_], s6);\n s7 = fmaf(xv, wp[7 * N_], s7);\n }\n#pragma unroll\n for (int off = 16; off > 0; off >>= 1) {\n s0 += __shfl_down_sync(0xffffffff, s0, off);\n s1 += __shfl_down_sync(0xffffffff, s1, off);\n s2 += __shfl_down_sync(0xffffffff, s2, off);\n s3 += __shfl_down_sync(0xffffffff, s3, off);\n s4 += __shfl_down_sync(0xffffffff, s4, off);\n s5 += __shfl_down_sync(0xffffffff, s5, off);\n s6 += __shfl_down_sync(0xffffffff, s6, off);\n s7 += __shfl_down_sync(0xffffffff, s7, off);\n }\n if (lane == 0) {\n float* yp = y + b * K_ + k0;\n const float* bp = bias + k0;\n yp[0] = s0 + bp[0];\n yp[1] = s1 + bp[1];\n yp[2] = s2 + bp[2];\n yp[3] = s3 + bp[3];\n yp[4] = s4 + bp[4];\n yp[5] = s5 + bp[5];\n yp[6] = s6 + bp[6];\n yp[7] = s7 + bp[7];\n }\n}\n\ntorch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {\n auto y = torch::empty({B_, K_}, x.options());\n vag_linear_kernel8<<<B_, WARPS_PER_BLOCK * 32>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>());\n return y;\n}\n'''\n\n_ext = load_inline(\n name='vag_linear_ext_final',\n cpp_sources=_cpp_src,\n cuda_sources=_cuda_src,\n functions=['vag_linear_forward'],\n extra_cuda_cflags=['-O3', '--use_fast_math'],\n verbose=False,\n)\n\nclass ModelNew(nn.Module):\n def __init__(self):\n super().__init__()\n self.proj = nn.Linear(4 * 32, 56, bias=True)\n\n def forward(self, x: torch.Tensor) -> torch.Tensor:\n return _ext.vag_linear_forward(x, self.proj.weight, self.proj.bias)\n"
}
result ← submit_kernel (ok)
oksubmit_kernel
submit_kernel PASSED: (5 / 5) correctness trials all passed.
Kernel runtime: 0.01 μs
Runtime stats: mean=0.01μs median=?μs std=0.00μs
Numerical precision: max_abs_err=2.38e-07 mean_abs_err=4.59e-08 max_rel_err=3.49e-05
Memory: 33.06 MB peak (ref: 33.07 MB, ratio: 0.9998x)
Kernel launches: 1 (ref: 14, fusion ratio: 14.0)
SOL score: 0.0034
final submitted kernel (97 lines, 3,080 chars) — full source, untruncated
import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline
_cpp_src = r'''
#include <torch/extension.h>
torch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias);
'''
_cuda_src = r'''
#include <torch/extension.h>
#include <cuda.h>
#include <cuda_runtime.h>
constexpr int R_ = 4;
constexpr int B_ = 12;
constexpr int H_ = 32;
constexpr int K_ = 56;
constexpr int N_ = R_ * H_;
constexpr int WARPS_PER_BLOCK = 7;
constexpr int KTILE = 8;
__global__ __launch_bounds__(WARPS_PER_BLOCK * 32, 4)
void vag_linear_kernel8(const float* __restrict__ x,
const float* __restrict__ w,
const float* __restrict__ bias,
float* __restrict__ y) {
int b = blockIdx.x;
int warp = threadIdx.x >> 5;
int lane = threadIdx.x & 31;
int k0 = warp * KTILE;
float s0=0.0f, s1=0.0f, s2=0.0f, s3=0.0f;
float s4=0.0f, s5=0.0f, s6=0.0f, s7=0.0f;
#pragma unroll
for (int rr = 0; rr < R_; ++rr) {
int n = rr * H_ + lane;
float xv = x[(rr * B_ + b) * H_ + lane];
const float* wp = w + k0 * N_ + n;
s0 = fmaf(xv, wp[0 * N_], s0);
s1 = fmaf(xv, wp[1 * N_], s1);
s2 = fmaf(xv, wp[2 * N_], s2);
s3 = fmaf(xv, wp[3 * N_], s3);
s4 = fmaf(xv, wp[4 * N_], s4);
s5 = fmaf(xv, wp[5 * N_], s5);
s6 = fmaf(xv, wp[6 * N_], s6);
s7 = fmaf(xv, wp[7 * N_], s7);
}
#pragma unroll
for (int off = 16; off > 0; off >>= 1) {
s0 += __shfl_down_sync(0xffffffff, s0, off);
s1 += __shfl_down_sync(0xffffffff, s1, off);
s2 += __shfl_down_sync(0xffffffff, s2, off);
s3 += __shfl_down_sync(0xffffffff, s3, off);
s4 += __shfl_down_sync(0xffffffff, s4, off);
s5 += __shfl_down_sync(0xffffffff, s5, off);
s6 += __shfl_down_sync(0xffffffff, s6, off);
s7 += __shfl_down_sync(0xffffffff, s7, off);
}
if (lane == 0) {
float* yp = y + b * K_ + k0;
const float* bp = bias + k0;
yp[0] = s0 + bp[0];
yp[1] = s1 + bp[1];
yp[2] = s2 + bp[2];
yp[3] = s3 + bp[3];
yp[4] = s4 + bp[4];
yp[5] = s5 + bp[5];
yp[6] = s6 + bp[6];
yp[7] = s7 + bp[7];
}
}
torch::Tensor vag_linear_forward(torch::Tensor x, torch::Tensor weight, torch::Tensor bias) {
auto y = torch::empty({B_, K_}, x.options());
vag_linear_kernel8<<<B_, WARPS_PER_BLOCK * 32>>>(x.data_ptr<float>(), weight.data_ptr<float>(), bias.data_ptr<float>(), y.data_ptr<float>());
return y;
}
'''
_ext = load_inline(
name='vag_linear_ext_final',
cpp_sources=_cpp_src,
cuda_sources=_cuda_src,
functions=['vag_linear_forward'],
extra_cuda_cflags=['-O3', '--use_fast_math'],
verbose=False,
)
class ModelNew(nn.Module):
def __init__(self):
super().__init__()
self.proj = nn.Linear(4 * 32, 56, bias=True)
def forward(self, x: torch.Tensor) -> torch.Tensor:
return _ext.vag_linear_forward(x, self.proj.weight, self.proj.bias)