Skip to content
KernelIndex
Search⌘K

submission 66907

BlueDream · python · License unknown

Use it

Vendorable · source mirrored · license unknownView source →

No package. Vendor the mirrored source: 230 lines, June 9 Researcher Reciprocity License v1.0.

vecsum4.py
curl "https://kernelindex.com/api/v1/implementations/kernelbot-vectorsum-v2-66907?include=source"
interfacepython
Compatibility
measured onNVIDIA A100
declared hardwareNVIDIA A100
architecturessm_80
dtypesfp32

Benchmark evidence

1 measurement across 1 GPU, fastest first.

Operation / workload
Hardware
Latency
Rank
Observed
Vector sum reductionsuite of 6 cases
NVIDIA A100
772.2µs
#86 of 96
2025-11-05

Reported · How evidence levels are derived →

Source and license

sourceavailable
revision digestsha256:1b07930a6287d3178f8af2d7e3f0a0e0ce9e8809045e2fc78a5432fe2657164b
license declaredunknown
license concludedunknown
authorsBlueDream
imported2026-08-15

Techniques

Extracted from the mirrored source by pattern, never inferred. Each row cites its line.

shared-memory__shared__ float shared_data[BLOCK_SIZE / 32];
vector-width = float4float4 v1 = *reinterpret_cast<const float4*>(&input[idx]);

Kernel source

vecsum4.py230 lines

import os
import torch
from torch.utils.cpp_extension import load_inline
from task import input_t, output_t

# Multi-architecture support
os.environ['TORCH_CUDA_ARCH_LIST'] = '8.0;8.9;9.0'  # A100, L4, B100

def custom_kernel(data: input_t) -> output_t:
    """
    Optimized CUDA implementation of vectorSum
    Args:
        data: Tuple of (input_tensor, output_tensor)
    Returns:
        Scalar value equal to the sum of all elements.
    """
    A, output_buffer = data  # Unpack the tuple
    A = A.contiguous()
    
    assert A.is_cuda, "Input tensor must be on GPU"
    assert A.dim() == 1, "Input tensor must be 1-dimensional"
    assert A.dtype == torch.float32, "Input tensor must be float32"
    
    N = A.numel()
    if N == 0:
        return torch.zeros((), dtype=A.dtype, device=A.device)
    
    cuda_source = """
    #include <torch/extension.h>
    #include <cuda_runtime.h>
    #include <cub/cub.cuh>
    #include <cuda/atomic>
    
    // Optimized warp reduction
    __inline__ __device__ float warpReduceSum(float val) {
        #pragma unroll
        for (int mask = 16; mask > 0; mask >>= 1) {
            val += __shfl_xor_sync(0xffffffff, val, mask);
        }
        return val;
    }
    
    // Single-pass reduction kernel with aggressive optimization
    template<int BLOCK_SIZE, int ITEMS_PER_THREAD>
    __global__ void __launch_bounds__(BLOCK_SIZE)
    vector_sum_kernel_fast(
        const float* __restrict__ input,
        float* __restrict__ output,
        const int N
    ) {
        // Shared memory for warp-level reductions
        __shared__ float shared_data[BLOCK_SIZE / 32];
        
        const int tid = threadIdx.x;
        const int gid = blockIdx.x * BLOCK_SIZE + tid;
        const int grid_size = gridDim.x * BLOCK_SIZE;
        const int warp_id = tid >> 5;
        const int lane_id = tid & 31;
        
        float sum = 0.0f;
        
        // Aggressive unrolling - each thread processes ITEMS_PER_THREAD elements
        int idx = gid;
        
        // Main loop - vectorized loads when possible
        if (N >= grid_size * 4) {
            // Fast path for large arrays - no boundary checks in main loop
            const int limit = N - (N % (grid_size * 4));
            
            while (idx < limit) {
                float4 v1 = *reinterpret_cast<const float4*>(&input[idx]);
                idx += grid_size;
                float4 v2 = *reinterpret_cast<const float4*>(&input[idx]);
                idx += grid_size;
                float4 v3 = *reinterpret_cast<const float4*>(&input[idx]);
                idx += grid_size;
                float4 v4 = *reinterpret_cast<const float4*>(&input[idx]);
                idx += grid_size;
                
                sum += (v1.x + v1.y + v1.z + v1.w) + 
                       (v2.x + v2.y + v2.z + v2.w) + 
                       (v3.x + v3.y + v3.z + v3.w) + 
                       (v4.x + v4.y + v4.z + v4.w);
            }
            
            // Handle remainder
            while (idx < N) {
                sum += input[idx];
                idx += grid_size;
            }
        } else {
            // Fallback for smaller arrays
            while (idx < N) {
                sum += input[idx];
                idx += grid_size;
            }
        }
        
        // Warp-level reduction
        sum = warpReduceSum(sum);
        
        // Write warp sums to shared memory
        if (lane_id == 0) {
            shared_data[warp_id] = sum;
        }
        __syncthreads();
        
        // Final reduction by first warp
        if (tid < 32) {
            sum = (tid < (BLOCK_SIZE / 32)) ? shared_data[tid] : 0.0f;
            sum = warpReduceSum(sum);
            
            // Use warp-aggregated atomic to reduce contention
            if (tid == 0) {
                atomicAdd(output, sum);
            }
        }
    }
    
    // CUB-based implementation for maximum performance
    torch::Tensor vector_sum_cuda_cub(torch::Tensor input) {
        const int N = input.numel();
        auto output = torch::zeros({}, input.options());
        
        if (N == 0) return output;
        
        // Use CUB for optimal performance
        size_t temp_storage_bytes = 0;
        cub::DeviceReduce::Sum(
            nullptr, temp_storage_bytes,
            input.data_ptr<float>(), output.data_ptr<float>(), N
        );
        
        auto temp_storage = torch::empty({(long)temp_storage_bytes}, 
                                        torch::TensorOptions()
                                        .dtype(torch::kUInt8)
                                        .device(input.device()));
        
        cub::DeviceReduce::Sum(
            temp_storage.data_ptr(), temp_storage_bytes,
            input.data_ptr<float>(), output.data_ptr<float>(), N
        );
        
        return output;
    }
    
    // Custom implementation for cases where CUB might not be optimal
    torch::Tensor vector_sum_cuda_custom(torch::Tensor input) {
        const int N = input.numel();
        auto output = torch::zeros({}, input.options());
        
        if (N == 0) return output;
        
        // Aggressive configuration for maximum occupancy
        const int BLOCK_SIZE = 256;
        const int ITEMS_PER_THREAD = 4;
        
        // Launch MANY blocks to saturate memory bandwidth
        int num_blocks;
        if (N < 1024) {
            num_blocks = 1;
        } else if (N < 1024 * 1024) {
            num_blocks = (N + BLOCK_SIZE - 1) / BLOCK_SIZE;
        } else {
            // For large arrays, use enough blocks to saturate bandwidth
            // Target: each block processes ~2K-4K elements
            num_blocks = std::min(65536, (N + 2048 - 1) / 2048);
            
            // Ensure we have enough blocks to saturate the GPU
            cudaDeviceProp prop;
            cudaGetDeviceProperties(&prop, 0);
            int min_blocks = prop.multiProcessorCount * 16;  // 16 blocks per SM
            num_blocks = std::max(num_blocks, min_blocks);
        }
        
        vector_sum_kernel_fast<BLOCK_SIZE, ITEMS_PER_THREAD>
            <<<num_blocks, BLOCK_SIZE>>>(
                input.data_ptr<float>(),
                output.data_ptr<float>(),
                N
            );
        
        cudaError_t err = cudaGetLastError();
        if (err != cudaSuccess) {
            throw std::runtime_error(cudaGetErrorString(err));
        }
        
        return output;
    }
    
    torch::Tensor vector_sum_cuda(torch::Tensor input) {
        // For best performance, use CUB for large arrays
        const int N = input.numel();
        
        // Use CUB for large arrays (it's highly optimized by NVIDIA)
        if (N > 1024 * 1024) {
            return vector_sum_cuda_cub(input);
        } else {
            // Use custom kernel for smaller arrays (less overhead)
            return vector_sum_cuda_custom(input);
        }
    }
    """
    
    cpp_source = """
    #include <torch/extension.h>
    torch::Tensor vector_sum_cuda(torch::Tensor input);
    PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
        m.def("vector_sum_cuda", &vector_sum_cuda, "Optimized vector sum");
    }
    """
    
    module = load_inline(
        name='vector_sum_ultra_optimized',
        cpp_sources=cpp_source,
        cuda_sources=cuda_source,
        extra_cuda_cflags=[
            '-O3',
            '--use_fast_math',
            '--expt-relaxed-constexpr',
            '-Xptxas="-v"',
            '-lineinfo'
        ],
        extra_include_paths=['/usr/local/cuda/include'],  # For CUB
        verbose=False
    )
    
    result = module.vector_sum_cuda(A)
    return result
scrolls · 230 lines total

Source code from GPU Mode and the KernelBot dataset · June 9 Researcher Reciprocity License v1.0

Changes from previous submission

Against this author's previous submission submission 66598.

+
import os
import torch
from torch.utils.cpp_extension import load_inline
from task import input_t, output_t
- # Optimize for L4 GPU architecture
- os.environ['TORCH_CUDA_ARCH_LIST'] = '8.9'
+ # Multi-architecture support
+ os.environ['TORCH_CUDA_ARCH_LIST'] = '8.0;8.9;9.0' # A100, L4, B100
def custom_kernel(data: input_t) -> output_t:
"""
- CUDA implementation of vectorSum with Kahan compensated summation.
-
+ Optimized CUDA implementation of vectorSum
Args:
data: Tuple of (input_tensor, output_tensor)
- - input_tensor: 1D tensor of shape (N,) with float32 values
- - output_tensor: Pre-allocated output tensor of shape (1,)
-
Returns:
- Scalar tensor containing the sum of all input elements
+ Scalar value equal to the sum of all elements.
"""
- # Unpack the input tuple
- input_tensor, output_tensor = data
+ A, output_buffer = data # Unpack the tuple
+ A = A.contiguous()
- # Ensure contiguous memory layout for optimal access
- A = input_tensor.contiguous()
-
- # Validation checks
assert A.is_cuda, "Input tensor must be on GPU"
assert A.dim() == 1, "Input tensor must be 1-dimensional"
assert A.dtype == torch.float32, "Input tensor must be float32"
N = A.numel()
-
- # Handle edge case of empty input
if N == 0:
- output_tensor.fill_(0.0)
- return output_tensor.squeeze()
+ return torch.zeros((), dtype=A.dtype, device=A.device)
- # CUDA kernel source code with Kahan summation for better precision
cuda_source = """
#include <torch/extension.h>
#include <cuda_runtime.h>
-
- // Kahan compensated summation for better numerical accuracy
- template <typename scalar_t>
- __inline__ __device__ void kahanSum(scalar_t& sum, scalar_t& c, scalar_t value) {
- scalar_t y = value - c;
- scalar_t t = sum + y;
- c = (t - sum) - y;
- sum = t;
- }
-
- // Warp-level reduction using shuffle instructions
- template <typename scalar_t>
- __inline__ __device__ scalar_t warpReduceSum(scalar_t val) {
- for (int offset = 16; offset > 0; offset /= 2) {
- val += __shfl_down_sync(0xffffffff, val, offset);
+ #include <cub/cub.cuh>
+ #include <cuda/atomic>
+
+ // Optimized warp reduction
+ __inline__ __device__ float warpReduceSum(float val) {
+ #pragma unroll
+ for (int mask = 16; mask > 0; mask >>= 1) {
+ val += __shfl_xor_sync(0xffffffff, val, mask);
}
return val;
}
-
- // Two-stage reduction: blocks -> final sum
- template <typename scalar_t>
- __global__ void vector_sum_kernel_stage1(
- const scalar_t* __restrict__ input,
- scalar_t* __restrict__ block_sums,
+
+ // Single-pass reduction kernel with aggressive optimization
+ template<int BLOCK_SIZE, int ITEMS_PER_THREAD>
+ __global__ void __launch_bounds__(BLOCK_SIZE)
+ vector_sum_kernel_fast(
+ const float* __restrict__ input,
+ float* __restrict__ output,
const int N
) {
- extern __shared__ __align__(sizeof(scalar_t)) char shared_mem_char[];
- scalar_t* sharedMem = reinterpret_cast<scalar_t*>(shared_mem_char);
-
+ // Shared memory for warp-level reductions
+ __shared__ float shared_data[BLOCK_SIZE / 32];
+
const int tid = threadIdx.x;
- const int bid = blockIdx.x;
- const int globalIdx = bid * blockDim.x + tid;
-
- // Kahan summation for each thread
- scalar_t threadSum = 0;
- scalar_t compensation = 0;
-
- for (int i = globalIdx; i < N; i += gridDim.x * blockDim.x) {
- kahanSum(threadSum, compensation, input[i]);
- }
-
- // Warp-level reduction
- threadSum = warpReduceSum(threadSum);
-
- // Store warp results to shared memory
- if (tid % 32 == 0) {
- sharedMem[tid / 32] = threadSum;
- }
- __syncthreads();
-
- // First warp reduces all warp sums
- if (tid < 32) {
- scalar_t val = (tid < (blockDim.x + 31) / 32) ? sharedMem[tid] : 0;
- scalar_t blockSum = warpReduceSum(val);
-
- if (tid == 0) {
- block_sums[bid] = blockSum;
+ const int gid = blockIdx.x * BLOCK_SIZE + tid;
+ const int grid_size = gridDim.x * BLOCK_SIZE;
+ const int warp_id = tid >> 5;
+ const int lane_id = tid & 31;
+
+ float sum = 0.0f;
+
+ // Aggressive unrolling - each thread processes ITEMS_PER_THREAD elements
+ int idx = gid;
+
+ // Main loop - vectorized loads when possible
+ if (N >= grid_size * 4) {
+ // Fast path for large arrays - no boundary checks in main loop
+ const int limit = N - (N % (grid_size * 4));
+
+ while (idx < limit) {
+ float4 v1 = *reinterpret_cast<const float4*>(&input[idx]);
+ idx += grid_size;
+ float4 v2 = *reinterpret_cast<const float4*>(&input[idx]);
+ idx += grid_size;
+ float4 v3 = *reinterpret_cast<const float4*>(&input[idx]);
+ idx += grid_size;
+ float4 v4 = *reinterpret_cast<const float4*>(&input[idx]);
+ idx += grid_size;
+
+ sum += (v1.x + v1.y + v1.z + v1.w) +
+ (v2.x + v2.y + v2.z + v2.w) +
+ (v3.x + v3.y + v3.z + v3.w) +
+ (v4.x + v4.y + v4.z + v4.w);
}
+
+ // Handle remainder
+ while (idx < N) {
+ sum += input[idx];
+ idx += grid_size;
+ }
+ } else {
+ // Fallback for smaller arrays
+ while (idx < N) {
+ sum += input[idx];
+ idx += grid_size;
+ }
}
- }
-
- template <typename scalar_t>
- __global__ void vector_sum_kernel_stage2(
- const scalar_t* __restrict__ block_sums,
- scalar_t* __restrict__ output,
- const int num_blocks
- ) {
- extern __shared__ __align__(sizeof(scalar_t)) char shared_mem_char[];
- scalar_t* sharedMem = reinterpret_cast<scalar_t*>(shared_mem_char);
-
- const int tid = threadIdx.x;
-
- // Kahan summation for final reduction
- scalar_t threadSum = 0;
- scalar_t compensation = 0;
-
- for (int i = tid; i < num_blocks; i += blockDim.x) {
- kahanSum(threadSum, compensation, block_sums[i]);
- }
-
+
// Warp-level reduction
- threadSum = warpReduceSum(threadSum);
-
- if (tid % 32 == 0) {
- sharedMem[tid / 32] = threadSum;
+ sum = warpReduceSum(sum);
+
+ // Write warp sums to shared memory
+ if (lane_id == 0) {
+ shared_data[warp_id] = sum;
}
__syncthreads();
-
+
+ // Final reduction by first warp
if (tid < 32) {
- scalar_t val = (tid < (blockDim.x + 31) / 32) ? sharedMem[tid] : 0;
- scalar_t finalSum = warpReduceSum(val);
-
+ sum = (tid < (BLOCK_SIZE / 32)) ? shared_data[tid] : 0.0f;
+ sum = warpReduceSum(sum);
+
+ // Use warp-aggregated atomic to reduce contention
if (tid == 0) {
- output[0] = finalSum;
+ atomicAdd(output, sum);
}
}
}
-
- torch::Tensor vector_sum_cuda(torch::Tensor input, torch::Tensor output) {
- TORCH_CHECK(input.device().is_cuda(), "Input must be a CUDA tensor");
- TORCH_CHECK(input.dim() == 1, "Input must be 1-dimensional");
+
+ // CUB-based implementation for maximum performance
+ torch::Tensor vector_sum_cuda_cub(torch::Tensor input) {
+ const int N = input.numel();
+ auto output = torch::zeros({}, input.options());
+ if (N == 0) return output;
+
+ // Use CUB for optimal performance
+ size_t temp_storage_bytes = 0;
+ cub::DeviceReduce::Sum(
+ nullptr, temp_storage_bytes,
+ input.data_ptr<float>(), output.data_ptr<float>(), N
+ );
+
+ auto temp_storage = torch::empty({(long)temp_storage_bytes},
+ torch::TensorOptions()
+ .dtype(torch::kUInt8)
+ .device(input.device()));
+
+ cub::DeviceReduce::Sum(
+ temp_storage.data_ptr(), temp_storage_bytes,
+ input.data_ptr<float>(), output.data_ptr<float>(), N
+ );
+
+ return output;
+ }
+
+ // Custom implementation for cases where CUB might not be optimal
+ torch::Tensor vector_sum_cuda_custom(torch::Tensor input) {
const int N = input.numel();
+ auto output = torch::zeros({}, input.options());
- if (N == 0) {
- output.fill_(0.0);
- return output;
- }
-
- const int blockSize = 256;
- const int numBlocks = min((N + blockSize - 1) / blockSize, 4096);
+ if (N == 0) return output;
- // Allocate intermediate storage for block sums
- auto block_sums = torch::empty({numBlocks}, input.options());
+ // Aggressive configuration for maximum occupancy
+ const int BLOCK_SIZE = 256;
+ const int ITEMS_PER_THREAD = 4;
- // Stage 1: Reduce input to per-block sums
- dim3 grid1(numBlocks);
- dim3 block1(blockSize);
- size_t shared_mem_size1 = (blockSize / 32) * sizeof(float);
+ // Launch MANY blocks to saturate memory bandwidth
+ int num_blocks;
+ if (N < 1024) {
+ num_blocks = 1;
+ } else if (N < 1024 * 1024) {
+ num_blocks = (N + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ } else {
+ // For large arrays, use enough blocks to saturate bandwidth
+ // Target: each block processes ~2K-4K elements
+ num_blocks = std::min(65536, (N + 2048 - 1) / 2048);
+
+ // Ensure we have enough blocks to saturate the GPU
+ cudaDeviceProp prop;
+ cudaGetDeviceProperties(&prop, 0);
+ int min_blocks = prop.multiProcessorCount * 16; // 16 blocks per SM
+ num_blocks = std::max(num_blocks, min_blocks);
+ }
- AT_DISPATCH_FLOATING_TYPES(input.scalar_type(), "vector_sum_kernel_stage1", ([&] {
- vector_sum_kernel_stage1<scalar_t><<<grid1, block1, shared_mem_size1>>>(
- input.data_ptr<scalar_t>(),
- block_sums.data_ptr<scalar_t>(),
+ vector_sum_kernel_fast<BLOCK_SIZE, ITEMS_PER_THREAD>
+ <<<num_blocks, BLOCK_SIZE>>>(
+ input.data_ptr<float>(),
+ output.data_ptr<float>(),
N
);
- }));
- // Stage 2: Reduce block sums to final result (deterministic, no atomics)
- dim3 grid2(1);
- dim3 block2(blockSize);
- size_t shared_mem_size2 = (blockSize / 32) * sizeof(float);
-
- AT_DISPATCH_FLOATING_TYPES(input.scalar_type(), "vector_sum_kernel_stage2", ([&] {
- vector_sum_kernel_stage2<scalar_t><<<grid2, block2, shared_mem_size2>>>(
- block_sums.data_ptr<scalar_t>(),
- output.data_ptr<scalar_t>(),
- numBlocks
- );
- }));
-
cudaError_t err = cudaGetLastError();
if (err != cudaSuccess) {
throw std::runtime_error(cudaGetErrorString(err));
}
-
+
return output;
}
+
+ torch::Tensor vector_sum_cuda(torch::Tensor input) {
+ // For best performance, use CUB for large arrays
+ const int N = input.numel();
+
+ // Use CUB for large arrays (it's highly optimized by NVIDIA)
+ if (N > 1024 * 1024) {
+ return vector_sum_cuda_cub(input);
+ } else {
+ // Use custom kernel for smaller arrays (less overhead)
+ return vector_sum_cuda_custom(input);
+ }
+ }
"""
-
- # C++ binding code
+
cpp_source = """
#include <torch/extension.h>
- torch::Tensor vector_sum_cuda(torch::Tensor input, torch::Tensor output);
-
+ torch::Tensor vector_sum_cuda(torch::Tensor input);
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
- m.def("vector_sum_cuda", &vector_sum_cuda, "Vector sum reduction (CUDA)");
+ m.def("vector_sum_cuda", &vector_sum_cuda, "Optimized vector sum");
}
"""
-
- # Compile and load the CUDA extension
+
module = load_inline(
- name='vector_sum_optimized',
+ name='vector_sum_ultra_optimized',
cpp_sources=cpp_source,
cuda_sources=cuda_source,
- extra_cuda_cflags=['-arch=sm_89', '-O3', '--use_fast_math'],
+ extra_cuda_cflags=[
+ '-O3',
+ '--use_fast_math',
+ '--expt-relaxed-constexpr',
+ '-Xptxas="-v"',
+ '-lineinfo'
+ ],
+ extra_include_paths=['/usr/local/cuda/include'], # For CUB
verbose=False
)
-
- # Execute the kernel and return the result
- result = module.vector_sum_cuda(A, output_tensor)
- return result.squeeze()
No newline at end of file
+
+ result = module.vector_sum_cuda(A)
+ return result
No newline at end of file
scrolls · 381 diff lines total

Best evidence level for this revision: reported

JSON