Skip to content
KernelIndex
Search⌘K

submission 230383

HayatoFujihara · python · License unknown

Use it

Vendorable · source mirrored · license unknownView source →

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

grayscale_v2_10.py
curl "https://kernelindex.com/api/v1/implementations/kernelbot-grayscale-v2-230383?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
RGB to grayscalesuite of 6 cases
NVIDIA A100
2.39ms
#7 of 137
2025-12-29

Reported · How evidence levels are derived →

Source and license

sourceavailable
revision digestsha256:a6871cc02bdfaae29c9fb09ddeb4c31a08746422b9535c58cd4056195cdee6ad
license declaredunknown
license concludedunknown
authorsHayatoFujihara
imported2026-08-15

Techniques

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

vector-width = ld.global.v4"ld.global.v4.f32 {%0, %1, %2, %3}, [%4];"

Kernel source

grayscale_v2_10.py115 lines
import torch
from torch.utils.cpp_extension import load_inline
from task import input_t, output_t

# =============================================================================
# Inline CUDA: float4 ベクトルロード版 RGB to Grayscale (Phase 3: Inline PTX)
# =============================================================================
# 目標: 2.47ms (Triton) → 2.38ms
#
# Phase 3 変更点:
#   - Inline PTX で ld.global.v4.f32 を明示的に使用
#   - LDG.128 命令を完全に強制
#   - コンパイラの最適化判断を完全にバイパス
#
# PTX 命令:
#   ld.global.v4.f32 {%0, %1, %2, %3}, [%4];
#   - 128-bit (16 bytes) 一括ロード
#   - 4 つの float を同時に取得

cuda_src = """
#include <cuda_runtime.h>

// Inline PTX による float4 ロード
__device__ __forceinline__ void load_float4_ptx(
    const float* ptr,
    float& r0, float& r1, float& r2, float& r3
) {
    asm volatile(
        "ld.global.v4.f32 {%0, %1, %2, %3}, [%4];"
        : "=f"(r0), "=f"(r1), "=f"(r2), "=f"(r3)
        : "l"(ptr)
    );
}

// RGB to Grayscale カーネル(Inline PTX 版)
__global__ void grayscale_kernel(
    const float* __restrict__ input,
    float* __restrict__ output,
    int n_pixels
) {
    int tid = blockIdx.x * blockDim.x + threadIdx.x;
    int pixel_base = tid * 4;

    if (pixel_base >= n_pixels) return;

    int base = pixel_base * 3;
    const float* ptr = input + base;

    // PTX で 128-bit ロード × 3 回
    float d0_x, d0_y, d0_z, d0_w;  // [R0, G0, B0, R1]
    float d1_x, d1_y, d1_z, d1_w;  // [G1, B1, R2, G2]
    float d2_x, d2_y, d2_z, d2_w;  // [B2, R3, G3, B3]

    load_float4_ptx(ptr,      d0_x, d0_y, d0_z, d0_w);
    load_float4_ptx(ptr + 4,  d1_x, d1_y, d1_z, d1_w);
    load_float4_ptx(ptr + 8,  d2_x, d2_y, d2_z, d2_w);

    // Grayscale 計算
    float4 gray;
    gray.x = d0_x * 0.2989f + d0_y * 0.5870f + d0_z * 0.1140f;  // Pixel 0
    gray.y = d0_w * 0.2989f + d1_x * 0.5870f + d1_y * 0.1140f;  // Pixel 1
    gray.z = d1_z * 0.2989f + d1_w * 0.5870f + d2_x * 0.1140f;  // Pixel 2
    gray.w = d2_y * 0.2989f + d2_z * 0.5870f + d2_w * 0.1140f;  // Pixel 3

    // float4 で出力
    *reinterpret_cast<float4*>(output + pixel_base) = gray;
}

torch::Tensor rgb_to_grayscale(torch::Tensor input, torch::Tensor output) {
    int n_pixels = output.numel();

    int threads = 256;
    int pixels_per_block = threads * 4;
    int blocks = (n_pixels + pixels_per_block - 1) / pixels_per_block;

    grayscale_kernel<<<blocks, threads>>>(
        input.data_ptr<float>(),
        output.data_ptr<float>(),
        n_pixels
    );

    return output;
}
"""

cpp_src = """
#include <torch/extension.h>

torch::Tensor rgb_to_grayscale(torch::Tensor input, torch::Tensor output);
"""

_module = None

def _get_module():
    global _module
    if _module is None:
        _module = load_inline(
            name='grayscale_cuda_float4_ptx',
            cuda_sources=[cuda_src],
            cpp_sources=[cpp_src],
            functions=['rgb_to_grayscale'],
            extra_cuda_cflags=['-O3', '--use_fast_math'],
            verbose=False
        )
    return _module


def custom_kernel(data: input_t) -> output_t:
    input_tensor, output_tensor = data

    module = _get_module()
    module.rgb_to_grayscale(input_tensor, output_tensor)

    return output_tensor
scrolls · 115 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 227417.

import torch
- import triton
- import triton.language as tl
+ from torch.utils.cpp_extension import load_inline
from task import input_t, output_t
# =============================================================================
- # Phase 1.3: 明示的分解版(並列乗算 + 最後に加算)
+ # Inline CUDA: float4 ベクトルロード版 RGB to Grayscale (Phase 3: Inline PTX)
# =============================================================================
- # 目標: 2.44ms → 2.38ms
+ # 目標: 2.47ms (Triton) → 2.38ms
#
- # 仮説: 累積加算(gray += x * coef)はFMA依存チェーンを形成
- # 並列乗算(term_x = x * coef)後に加算することでILP向上
- # 3つの乗算が並列実行可能になる
+ # Phase 3 変更点:
+ # - Inline PTX で ld.global.v4.f32 を明示的に使用
+ # - LDG.128 命令を完全に強制
+ # - コンパイラの最適化判断を完全にバイパス
#
- # Phase 1.1 結果: G→R→B = 2.47ms(効果なし)
- # Phase 1.2 結果: B→R→G = 2.47ms(効果なし)
- #
- # 変更点:
- # - 3つのチャンネルを並列でロード(独立Block Pointer)
- # - 3つの乗算を並列で実行
- # - 最後に3項を加算
+ # PTX 命令:
+ # ld.global.v4.f32 {%0, %1, %2, %3}, [%4];
+ # - 128-bit (16 bytes) 一括ロード
+ # - 4 つの float を同時に取得
- @triton.autotune(
- configs=[
- # 中ブロック
- triton.Config({'BLOCK_SIZE': 2048}, num_warps=4, num_stages=3),
- triton.Config({'BLOCK_SIZE': 2048}, num_warps=4, num_stages=4),
- triton.Config({'BLOCK_SIZE': 2048}, num_warps=4, num_stages=5),
+ cuda_src = """
+ #include <cuda_runtime.h>
- # 大ブロック
- triton.Config({'BLOCK_SIZE': 4096}, num_warps=4, num_stages=4),
- triton.Config({'BLOCK_SIZE': 4096}, num_warps=4, num_stages=5),
- triton.Config({'BLOCK_SIZE': 4096}, num_warps=8, num_stages=3),
- triton.Config({'BLOCK_SIZE': 4096}, num_warps=8, num_stages=4),
- triton.Config({'BLOCK_SIZE': 4096}, num_warps=8, num_stages=5),
+ // Inline PTX による float4 ロード
+ __device__ __forceinline__ void load_float4_ptx(
+ const float* ptr,
+ float& r0, float& r1, float& r2, float& r3
+ ) {
+ asm volatile(
+ "ld.global.v4.f32 {%0, %1, %2, %3}, [%4];"
+ : "=f"(r0), "=f"(r1), "=f"(r2), "=f"(r3)
+ : "l"(ptr)
+ );
+ }
- # 超大ブロック
- triton.Config({'BLOCK_SIZE': 8192}, num_warps=8, num_stages=3),
- triton.Config({'BLOCK_SIZE': 8192}, num_warps=8, num_stages=4),
- triton.Config({'BLOCK_SIZE': 8192}, num_warps=8, num_stages=5),
- triton.Config({'BLOCK_SIZE': 8192}, num_warps=16, num_stages=3),
- triton.Config({'BLOCK_SIZE': 8192}, num_warps=16, num_stages=4),
- ],
- key=['n_elements'],
- )
- @triton.jit
- def grayscale_kernel(
- input_ptr, output_ptr,
- n_elements,
- BLOCK_SIZE: tl.constexpr
- ):
- pid = tl.program_id(axis=0)
+ // RGB to Grayscale カーネル(Inline PTX 版)
+ __global__ void grayscale_kernel(
+ const float* __restrict__ input,
+ float* __restrict__ output,
+ int n_pixels
+ ) {
+ int tid = blockIdx.x * blockDim.x + threadIdx.x;
+ int pixel_base = tid * 4;
- # 独立した3つのBlock Pointer(並列ロード可能)
- ptr_r = tl.make_block_ptr(
- base=input_ptr,
- shape=(n_elements, 3),
- strides=(3, 1),
- offsets=(pid * BLOCK_SIZE, 0),
- block_shape=(BLOCK_SIZE, 1),
- order=(1, 0)
- )
- ptr_g = tl.make_block_ptr(
- base=input_ptr,
- shape=(n_elements, 3),
- strides=(3, 1),
- offsets=(pid * BLOCK_SIZE, 1),
- block_shape=(BLOCK_SIZE, 1),
- order=(1, 0)
- )
- ptr_b = tl.make_block_ptr(
- base=input_ptr,
- shape=(n_elements, 3),
- strides=(3, 1),
- offsets=(pid * BLOCK_SIZE, 2),
- block_shape=(BLOCK_SIZE, 1),
- order=(1, 0)
- )
+ if (pixel_base >= n_pixels) return;
- # 並列ロード(依存関係なし)
- r = tl.load(ptr_r, boundary_check=(0,), padding_option="zero")
- g = tl.load(ptr_g, boundary_check=(0,), padding_option="zero")
- b = tl.load(ptr_b, boundary_check=(0,), padding_option="zero")
+ int base = pixel_base * 3;
+ const float* ptr = input + base;
- # 並列乗算(依存関係なし、ILP最大化)
- term_r = r * 0.2989
- term_g = g * 0.5870
- term_b = b * 0.1140
+ // PTX で 128-bit ロード × 3 回
+ float d0_x, d0_y, d0_z, d0_w; // [R0, G0, B0, R1]
+ float d1_x, d1_y, d1_z, d1_w; // [G1, B1, R2, G2]
+ float d2_x, d2_y, d2_z, d2_w; // [B2, R3, G3, B3]
- # 最後に加算
- gray = term_r + term_g + term_b
+ load_float4_ptx(ptr, d0_x, d0_y, d0_z, d0_w);
+ load_float4_ptx(ptr + 4, d1_x, d1_y, d1_z, d1_w);
+ load_float4_ptx(ptr + 8, d2_x, d2_y, d2_z, d2_w);
- # Output (1Dポインタ)
- offs = pid * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)
- mask = offs < n_elements
- tl.store(output_ptr + offs, tl.reshape(gray, (BLOCK_SIZE,)), mask=mask)
+ // Grayscale 計算
+ float4 gray;
+ gray.x = d0_x * 0.2989f + d0_y * 0.5870f + d0_z * 0.1140f; // Pixel 0
+ gray.y = d0_w * 0.2989f + d1_x * 0.5870f + d1_y * 0.1140f; // Pixel 1
+ gray.z = d1_z * 0.2989f + d1_w * 0.5870f + d2_x * 0.1140f; // Pixel 2
+ gray.w = d2_y * 0.2989f + d2_z * 0.5870f + d2_w * 0.1140f; // Pixel 3
+ // float4 で出力
+ *reinterpret_cast<float4*>(output + pixel_base) = gray;
+ }
+ torch::Tensor rgb_to_grayscale(torch::Tensor input, torch::Tensor output) {
+ int n_pixels = output.numel();
+
+ int threads = 256;
+ int pixels_per_block = threads * 4;
+ int blocks = (n_pixels + pixels_per_block - 1) / pixels_per_block;
+
+ grayscale_kernel<<<blocks, threads>>>(
+ input.data_ptr<float>(),
+ output.data_ptr<float>(),
+ n_pixels
+ );
+
+ return output;
+ }
+ """
+
+ cpp_src = """
+ #include <torch/extension.h>
+
+ torch::Tensor rgb_to_grayscale(torch::Tensor input, torch::Tensor output);
+ """
+
+ _module = None
+
+ def _get_module():
+ global _module
+ if _module is None:
+ _module = load_inline(
+ name='grayscale_cuda_float4_ptx',
+ cuda_sources=[cuda_src],
+ cpp_sources=[cpp_src],
+ functions=['rgb_to_grayscale'],
+ extra_cuda_cflags=['-O3', '--use_fast_math'],
+ verbose=False
+ )
+ return _module
+
+
def custom_kernel(data: input_t) -> output_t:
input_tensor, output_tensor = data
- n_elements = output_tensor.numel()
- grid = lambda META: (triton.cdiv(n_elements, META['BLOCK_SIZE']),)
+ module = _get_module()
+ module.rgb_to_grayscale(input_tensor, output_tensor)
- grayscale_kernel[grid](
- input_tensor, output_tensor,
- n_elements
- )
-
return output_tensor
scrolls · 202 diff lines total

Best evidence level for this revision: reported

JSON