GPUCodeForces/S1 codes/geglu_sample/geglu_cuda.py

90 lines
3.2 KiB
Python

import torch
import torch.nn as nn
from torch.utils.cpp_extension import load_inline
class ModelNew(nn.Module):
def __init__(self):
super().__init__()
self.op = load_inline(
name="geglu_fused_tanh_v1",
cpp_sources="""
#include <torch/extension.h>
torch::Tensor geglu_cuda(torch::Tensor input);
""",
cuda_sources="""
#include <torch/extension.h>
#include <cuda_runtime.h>
__device__ __forceinline__ float gelu_tanh(float x) {
const float kAlpha = 0.7978845608028654f;
const float kBeta = 0.044715f;
float x3 = x * x * x;
float inner = kAlpha * (x + kBeta * x3);
return 0.5f * x * (1.0f + tanhf(inner));
}
__global__ void geglu_kernel(
const float* __restrict__ input,
float* __restrict__ output,
long long output_numel,
int hidden,
int input_last_dim
) {
long long idx = blockIdx.x * blockDim.x + threadIdx.x;
long long stride = (long long)blockDim.x * gridDim.x;
for (long long i = idx; i < output_numel; i += stride) {
int col = i % hidden;
long long row = i / hidden;
long long base = row * input_last_dim + col;
float value = input[base];
float gate = input[base + hidden];
output[i] = value * gelu_tanh(gate);
}
}
torch::Tensor geglu_cuda(torch::Tensor input) {
TORCH_CHECK(input.is_cuda(), "input must be a CUDA tensor");
TORCH_CHECK(input.scalar_type() == torch::kFloat32, "input must be float32");
TORCH_CHECK(input.dim() >= 1, "input must have at least one dimension");
auto x = input.contiguous();
int input_last_dim = x.size(-1);
TORCH_CHECK(input_last_dim % 2 == 0, "last dimension must be even for GEGLU");
int hidden = input_last_dim / 2;
auto out_sizes = x.sizes().vec();
out_sizes.back() = hidden;
auto output = torch::empty(out_sizes, x.options());
long long output_numel = output.numel();
if (output_numel == 0) {
return output;
}
int threads = 256;
int blocks = (int)((output_numel + threads - 1) / threads);
if (blocks > 65535) {
blocks = 65535;
}
geglu_kernel<<<blocks, threads>>>(
x.data_ptr<float>(),
output.data_ptr<float>(),
output_numel,
hidden,
input_last_dim
);
return output;
}
""",
functions=["geglu_cuda"],
extra_cuda_cflags=["-O3", "--use_fast_math"],
verbose=False,
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
return self.op.geglu_cuda(x)