Day 98

GPU Kernels Learning Journey

Description

### Files: `leaky_relu.cu` I optimized my previous code that applies the Leaky ReLU (Leaky Rectified Linear Unit) activation function on an input matrix.

Code Files

leaky_relu.cu

#include <cuda_runtime.h>



__global__ void leaky_relu_vec4_kernel(
    const float* __restrict__ input,
    float          alpha,
    float* __restrict__ output,
    size_t         total_vec4,
    size_t         total_floats)
{
    const float4* in4  = reinterpret_cast<const float4*>(input);
    float4*       out4 = reinterpret_cast<float4*>(output);

    // global thread index and total threads
    size_t idx    = blockIdx.x * blockDim.x + threadIdx.x;
    size_t stride = gridDim.x * blockDim.x;

    // 1) Process in float4 chunks
    for (size_t v = idx; v < total_vec4; v += stride) {
        // I used __ldg for read-only cache
        float4 x = __ldg(&in4[v]);
        // And we use branchless LeakyReLU per lane
        x.x = fmaxf(x.x, alpha * x.x);
        x.y = fmaxf(x.y, alpha * x.y);
        x.z = fmaxf(x.z, alpha * x.z);
        x.w = fmaxf(x.w, alpha * x.w);
        out4[v] = x;
    }

    // 2) Handle any remaining floats
    size_t offset = total_vec4 * 4;
    for (size_t i = offset + idx; i < total_floats; i += stride) {
        float v = __ldg(&input[i]);
        output[i] = fmaxf(v, alpha * v);
    }
}


extern "C" void solution(
    const float* input,
    float         alpha,
    float*       output,
    size_t        M,
    size_t        N)
{
    size_t total_floats = M * N;
    size_t total_vec4   = total_floats / 4;

    constexpr int TPB = 256;
    int blocks = (total_vec4 + TPB - 1) / TPB;
    if (blocks < 1) blocks = 1;

    leaky_relu_vec4_kernel<<<blocks, TPB>>>(
        input, alpha, output,
        total_vec4, total_floats
    );
}