submission 781696
brianyu · python · License unknown
Use it
Vendorable · source mirrored · license unknownView source →
No package. Vendor the mirrored source: 215 lines, June 9 Researcher Reciprocity License v1.0.
v02_bucket_counting_cuda.py
curl "https://kernelindex.com/api/v1/implementations/kernelbot-sort-v2-781696?include=source"interfacepython
Compatibility
measured onNVIDIA A100
declared hardwareNVIDIA A100
architecturessm_80
dtypesfp32
Benchmark evidence
1 measurement across 1 GPU, fastest first.
Reported · How evidence levels are derived →
Source and license
sourceavailable
revision digestsha256:ac21d602895f9241dec5cec9db2c093bb6cd5b32eb5c0ecea1c3a9b002094763
license declaredunknown
license concludedunknown
authorsbrianyu
imported2026-08-15
Techniques
Extracted from the mirrored source by pattern, never inferred. Each row cites its line.
shared-memory
__shared__ float shared[kThreads];Kernel source
v02_bucket_counting_cuda.py215 lines
#!POPCORN leaderboard sort_v2
#!POPCORN gpus A100
from __future__ import annotations
import os
from typing import Any
import torch
from task import input_t, output_t
from torch.utils.cpp_extension import load_inline
BPU = 64
BIAS = 16
EXACT_LIMIT = 100000
_EXT: Any = None
def _get_ext() -> Any:
global _EXT
if _EXT is not None:
return _EXT
if not torch.cuda.is_available():
raise RuntimeError("CUDA is required")
os.environ["TORCH_CUDA_ARCH_LIST"] = "8.0"
os.environ["MAX_JOBS"] = "4"
cpp_src = r"""
#include <torch/extension.h>
torch::Tensor sort_v2_bucket_counting_cuda(torch::Tensor values, torch::Tensor output);
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
m.def("sort_v2_bucket_counting_cuda", &sort_v2_bucket_counting_cuda, "sort_v2 bucket counting cuda");
}
"""
cuda_src = r"""
#include <torch/extension.h>
#include <cub/cub.cuh>
#include <cuda.h>
#include <cuda_runtime.h>
#include <cmath>
#include <cstdint>
namespace {
constexpr int kBpu = 64;
constexpr int kBias = 16;
constexpr int kThreads = 256;
static inline int64_t ceil_div_i64(int64_t a, int64_t b) {
return (a + b - 1) / b;
}
static inline void cuda_check(cudaError_t status, const char* msg) {
TORCH_CHECK(status == cudaSuccess, msg, ": ", cudaGetErrorString(status));
}
__device__ __forceinline__ int bucket_id(float x, float base, int bucket_count) {
int q = static_cast<int>(floorf((x - base + static_cast<float>(kBias)) * static_cast<float>(kBpu)));
q = q < 0 ? 0 : q;
q = q >= bucket_count ? bucket_count - 1 : q;
return q;
}
__global__ void estimate_base_kernel(
const float* __restrict__ values,
float* __restrict__ base_out,
int64_t cols) {
__shared__ float shared[kThreads];
const int tid = threadIdx.x;
float sum = 0.0f;
for (int64_t i = tid; i < cols; i += blockDim.x) {
sum += values[i];
}
shared[tid] = sum;
__syncthreads();
for (int stride = blockDim.x >> 1; stride > 0; stride >>= 1) {
if (tid < stride) {
shared[tid] += shared[tid + stride];
}
__syncthreads();
}
if (tid == 0) {
base_out[0] = nearbyintf(shared[0] / static_cast<float>(cols));
}
}
__global__ void histogram_kernel(
const float* __restrict__ values,
const float* __restrict__ base,
int* __restrict__ counts,
int64_t n,
int bucket_count) {
const int64_t idx = static_cast<int64_t>(blockIdx.x) * blockDim.x + threadIdx.x;
const int64_t stride = static_cast<int64_t>(blockDim.x) * gridDim.x;
const float b = base[0];
for (int64_t i = idx; i < n; i += stride) {
const int q = bucket_id(values[i], b, bucket_count);
atomicAdd(counts + q, 1);
}
}
__global__ void scatter_kernel(
const float* __restrict__ values,
const float* __restrict__ base,
int* __restrict__ offsets,
float* __restrict__ output,
int64_t n,
int bucket_count) {
const int64_t idx = static_cast<int64_t>(blockIdx.x) * blockDim.x + threadIdx.x;
const int64_t stride = static_cast<int64_t>(blockDim.x) * gridDim.x;
const float b = base[0];
for (int64_t i = idx; i < n; i += stride) {
const float x = values[i];
const int q = bucket_id(x, b, bucket_count);
const int pos = atomicAdd(offsets + q, 1);
output[pos] = x;
}
}
} // namespace
torch::Tensor sort_v2_bucket_counting_cuda(torch::Tensor values, torch::Tensor output) {
TORCH_CHECK(values.is_cuda(), "values must be CUDA");
TORCH_CHECK(output.is_cuda(), "output must be CUDA");
TORCH_CHECK(values.scalar_type() == torch::kFloat32, "values must be float32");
TORCH_CHECK(output.scalar_type() == torch::kFloat32, "output must be float32");
TORCH_CHECK(values.is_contiguous(), "values must be contiguous");
TORCH_CHECK(output.is_contiguous(), "output must be contiguous");
const int64_t n = values.numel();
const int64_t rows = static_cast<int64_t>(std::sqrt(static_cast<double>(n)));
const int64_t cols = ceil_div_i64(n, rows);
const int bucket_count = static_cast<int>((rows + 2 * kBias) * kBpu);
auto int_opts = values.options().dtype(torch::kInt32);
auto byte_opts = values.options().dtype(torch::kUInt8);
auto counts = torch::empty({bucket_count}, int_opts);
auto offsets = torch::empty({bucket_count}, int_opts);
auto base = torch::empty({1}, values.options());
cuda_check(cudaMemsetAsync(counts.data_ptr<int>(), 0, bucket_count * sizeof(int)), "cudaMemsetAsync failed");
estimate_base_kernel<<<1, kThreads>>>(
values.data_ptr<float>(),
base.data_ptr<float>(),
cols);
cuda_check(cudaGetLastError(), "estimate_base_kernel launch failed");
const int blocks = static_cast<int>(std::min<int64_t>(ceil_div_i64(n, kThreads), 4096));
histogram_kernel<<<blocks, kThreads>>>(
values.data_ptr<float>(),
base.data_ptr<float>(),
counts.data_ptr<int>(),
n,
bucket_count);
cuda_check(cudaGetLastError(), "histogram_kernel launch failed");
void* temp_storage = nullptr;
size_t temp_bytes = 0;
cub::DeviceScan::ExclusiveSum(
temp_storage,
temp_bytes,
counts.data_ptr<int>(),
offsets.data_ptr<int>(),
bucket_count);
auto temp = torch::empty({static_cast<int64_t>(temp_bytes)}, byte_opts);
cub::DeviceScan::ExclusiveSum(
temp.data_ptr<uint8_t>(),
temp_bytes,
counts.data_ptr<int>(),
offsets.data_ptr<int>(),
bucket_count);
scatter_kernel<<<blocks, kThreads>>>(
values.data_ptr<float>(),
base.data_ptr<float>(),
offsets.data_ptr<int>(),
output.data_ptr<float>(),
n,
bucket_count);
cuda_check(cudaGetLastError(), "scatter_kernel launch failed");
return output;
}
"""
_EXT = load_inline(
name="sort_v2_bucket_counting_v02",
cpp_sources=cpp_src,
cuda_sources=cuda_src,
functions=None,
extra_cuda_cflags=["-O3", "-std=c++17", "-arch=sm_80", "--use_fast_math"],
extra_cflags=["-O3", "-std=c++17"],
with_cuda=True,
verbose=False,
)
return _EXT
def custom_kernel(data: input_t) -> output_t:
values, output = data
if values.numel() < EXACT_LIMIT:
output[...] = torch.sort(values)[0]
return output
return _get_ext().sort_v2_bucket_counting_cuda(values, output)
scrolls · 215 lines total
Source code from GPU Mode and the KernelBot dataset · June 9 Researcher Reciprocity License v1.0
Best evidence level for this revision: reported
JSON