Skip to content
KernelIndex
Search⌘K

submission 677272

ngolhn · python · License unknown

Use it

Vendorable · source mirrored · license unknownView source →

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

submission.py
curl "https://kernelindex.com/api/v1/implementations/kernelbot-histogram-v2-677272?include=source"
interfacepython
Compatibility
measured onNVIDIA B200
declared hardwareNVIDIA B200
architecturessm_100
dtypesuint8

Benchmark evidence

1 measurement across 1 GPU, fastest first.

Operation / workload
Hardware
Latency
Rank
Observed
Histogramsuite of 6 cases
NVIDIA B200
11.3µs
#2 of 54
2026-03-31

Reported · How evidence levels are derived →

Source and license

sourceavailable
revision digestsha256:17c8c4caebabf4999005ae9c425a6a445723cc2f02a1a3865427f08b0435ab37
license declaredunknown
license concludedunknown
authorsngolhn
imported2026-08-15

Techniques

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

shared-memoryextern __shared__ unsigned int smem_hist[];
vector-width = uint4reinterpret_cast<uint4*>(output)[tid] = make_uint4(0u, 0u, 0u, 0u);

Kernel source

submission.py99 lines
#!POPCORN leaderboard histogram_v2
#!POPCORN gpu B200

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

# Kernel with minimal C++ wrapper — just the raw kernel launch, nothing else
cuda_src = r"""
#include <torch/extension.h>
#include <cuda_runtime.h>

// Kernel: identical to sm100_notail_v2
__global__ void __launch_bounds__(256, 4)
histogram_kernel(const uint8_t* __restrict__ data, int64_t* __restrict__ output, int N) {
    extern __shared__ unsigned int smem_hist[];
    const int tid = threadIdx.x;

    smem_hist[tid] = 0u;

    if (blockIdx.x == 0 && tid < 128) {
        reinterpret_cast<uint4*>(output)[tid] = make_uint4(0u, 0u, 0u, 0u);
    }
    __syncthreads();

    const int vec_n = N >> 4;
    const uint4* data_vec = reinterpret_cast<const uint4*>(data);
    int idx = blockIdx.x * blockDim.x + tid;
    const int stride = blockDim.x * gridDim.x;

    const int vec_n_pairs = vec_n >> 1;
    for (int i = idx; i < vec_n_pairs; i += stride) {
        uint4 val0 = __ldg(&data_vec[i * 2]);
        uint4 val1 = __ldg(&data_vec[i * 2 + 1]);
        const uint8_t* b0 = reinterpret_cast<const uint8_t*>(&val0);
        const uint8_t* b1 = reinterpret_cast<const uint8_t*>(&val1);
        #pragma unroll
        for (int j = 0; j < 16; j++) {
            atomicAdd(&smem_hist[b0[j]], 1u);
        }
        #pragma unroll
        for (int j = 0; j < 16; j++) {
            atomicAdd(&smem_hist[b1[j]], 1u);
        }
    }

    __syncthreads();

    if (smem_hist[tid] > 0u) {
        atomicAdd(reinterpret_cast<unsigned long long*>(&output[tid]),
                  static_cast<unsigned long long>(smem_hist[tid]));
    }
}

// Minimal wrapper: take raw pointers + N, avoid any torch overhead in the hot path
void histogram_raw(int64_t data_ptr, int64_t output_ptr, int N) {
    histogram_kernel<<<256, 256, 256*sizeof(unsigned int)>>>(
        reinterpret_cast<uint8_t*>(data_ptr),
        reinterpret_cast<int64_t*>(output_ptr),
        N);
}

// Standard wrapper for warmup
void histogram_inplace(torch::Tensor data, torch::Tensor output) {
    const int N = data.numel();
    histogram_kernel<<<256, 256, 256*sizeof(unsigned int)>>>(
        data.data_ptr<uint8_t>(), output.data_ptr<int64_t>(), N);
}
"""

cpp_src = r"""
void histogram_raw(int64_t data_ptr, int64_t output_ptr, int N);
void histogram_inplace(torch::Tensor data, torch::Tensor output);
"""

_ext = load_inline(
    name="histogram_sm100_v3",
    cpp_sources=cpp_src,
    cuda_sources=cuda_src,
    functions=["histogram_raw", "histogram_inplace"],
    with_cuda=True,
    extra_cflags=["-O3", "-std=c++17"],
    extra_cuda_cflags=["-O3", "--use_fast_math", "-std=c++17",
                       "-gencode=arch=compute_100,code=sm_100"],
    verbose=False,
)

# Cache N for the benchmark size to avoid recomputing
_cached_N = None


def custom_kernel(data: input_t) -> output_t:
    global _cached_N
    data_tensor, output_tensor = data
    N = data_tensor.numel()
    # Use raw pointer path to skip torch tensor overhead in pybind11
    _ext.histogram_raw(data_tensor.data_ptr(), output_tensor.data_ptr(), N)
    return output_tensor
scrolls · 99 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 677175.

⋯ 4 unchanged lines
from task import input_t, output_t
from torch.utils.cpp_extension import load_inline
+ # Kernel with minimal C++ wrapper — just the raw kernel launch, nothing else
cuda_src = r"""
#include <torch/extension.h>
#include <cuda_runtime.h>
+ // Kernel: identical to sm100_notail_v2
__global__ void __launch_bounds__(256, 4)
histogram_kernel(const uint8_t* __restrict__ data, int64_t* __restrict__ output, int N) {
extern __shared__ unsigned int smem_hist[];
⋯ 1 unchanged lines
smem_hist[tid] = 0u;
- // Vectorized output zeroing with uint4
if (blockIdx.x == 0 && tid < 128) {
reinterpret_cast<uint4*>(output)[tid] = make_uint4(0u, 0u, 0u, 0u);
}
⋯ 4 unchanged lines
int idx = blockIdx.x * blockDim.x + tid;
const int stride = blockDim.x * gridDim.x;
- // Process pairs of uint4 (32 bytes = 32 elements per iteration)
const int vec_n_pairs = vec_n >> 1;
for (int i = idx; i < vec_n_pairs; i += stride) {
uint4 val0 = __ldg(&data_vec[i * 2]);
⋯ 18 unchanged lines
}
}
+ // Minimal wrapper: take raw pointers + N, avoid any torch overhead in the hot path
+ void histogram_raw(int64_t data_ptr, int64_t output_ptr, int N) {
+ histogram_kernel<<<256, 256, 256*sizeof(unsigned int)>>>(
+ reinterpret_cast<uint8_t*>(data_ptr),
+ reinterpret_cast<int64_t*>(output_ptr),
+ N);
+ }
+
+ // Standard wrapper for warmup
void histogram_inplace(torch::Tensor data, torch::Tensor output) {
const int N = data.numel();
histogram_kernel<<<256, 256, 256*sizeof(unsigned int)>>>(
⋯ 2 unchanged lines
"""
cpp_src = r"""
+ void histogram_raw(int64_t data_ptr, int64_t output_ptr, int N);
void histogram_inplace(torch::Tensor data, torch::Tensor output);
"""
_ext = load_inline(
- name="histogram_sm100_notail_v2",
+ name="histogram_sm100_v3",
cpp_sources=cpp_src,
cuda_sources=cuda_src,
- functions=["histogram_inplace"],
+ functions=["histogram_raw", "histogram_inplace"],
with_cuda=True,
extra_cflags=["-O3", "-std=c++17"],
extra_cuda_cflags=["-O3", "--use_fast_math", "-std=c++17",
⋯ 1 unchanged lines
verbose=False,
)
+ # Cache N for the benchmark size to avoid recomputing
+ _cached_N = None
+
def custom_kernel(data: input_t) -> output_t:
+ global _cached_N
data_tensor, output_tensor = data
- _ext.histogram_inplace(data_tensor, output_tensor)
+ N = data_tensor.numel()
+ # Use raw pointer path to skip torch tensor overhead in pybind11
+ _ext.histogram_raw(data_tensor.data_ptr(), output_tensor.data_ptr(), N)
return output_tensor
scrolls · 79 diff lines total

Best evidence level for this revision: reported

JSON