Skip to content
KernelIndex
Search⌘K

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.

Operation / workload
Hardware
Latency
Rank
Observed
Sortsuite of 5 cases
NVIDIA A100
6.39ms
#12 of 28
2026-05-09

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