Download benchmarks/benchmark.py from flashrt/flashrt-gemm-epilogues: direct link, hf CLI and curl.
- Browser
- Download file 8.65 kB
-
https://huggingface.co/flashrt/flashrt-gemm-epilogues/resolve/main/benchmarks/benchmark.py
- Command line
-
hf download hf://flashrt/flashrt-gemm-epilogues/benchmarks/benchmark.py
-
curl -L -o benchmark.py https://huggingface.co/flashrt/flashrt-gemm-epilogues/resolve/main/benchmarks/benchmark.py
8.65 kB
| import torch | |
| from kernels.benchmark import Benchmark | |
| _original_allclose = torch.allclose | |
| def _fp8_dtype() -> torch.dtype: | |
| if torch.version.hip is not None and hasattr(torch, "float8_e4m3fnuz"): | |
| return torch.float8_e4m3fnuz | |
| return torch.float8_e4m3fn | |
| def _fp8_max() -> float: | |
| return 240.0 if torch.version.hip is not None else 448.0 | |
| def _is_fp8_dtype(dtype: torch.dtype) -> bool: | |
| return dtype == torch.float8_e4m3fn or ( | |
| hasattr(torch, "float8_e4m3fnuz") and dtype == torch.float8_e4m3fnuz | |
| ) | |
| def _flashrt_allclose(input, other, rtol=1e-05, atol=1e-08, equal_nan=False): | |
| if _is_fp8_dtype(input.dtype) or _is_fp8_dtype(other.dtype): | |
| return _original_allclose( | |
| input.float(), | |
| other.float(), | |
| rtol=0, | |
| atol=0, | |
| equal_nan=equal_nan, | |
| ) | |
| return _original_allclose(input, other, rtol=rtol, atol=atol, equal_nan=equal_nan) | |
| torch.allclose = _flashrt_allclose | |
| QUANT_SHAPES = [ | |
| ("decode_m1", 1, 4096), | |
| ("decode_m2", 2, 4096), | |
| ("decode_m4", 4, 4096), | |
| ("decode_m8", 8, 4096), | |
| ("small_m16", 16, 4096), | |
| ("small_m32", 32, 4096), | |
| ("prefill_m64", 64, 4096), | |
| ("prefill_m128", 128, 4096), | |
| ("prefill_m256", 256, 4096), | |
| ("wide_n8192_m16", 16, 8192), | |
| ("wide_n8192_m128", 128, 8192), | |
| ("vla_n12288_m16", 16, 12288), | |
| ("vla_n12288_m64", 64, 12288), | |
| ("vla_n16384_m16", 16, 16384), | |
| ("vla_n16384_m64", 64, 16384), | |
| ] | |
| class BiasGeluFp8QuantizeBenchmark(Benchmark): | |
| seed = 1 | |
| def _setup_shape(self, m: int, n: int) -> None: | |
| self.input = torch.randn((m, n), device=self.device, dtype=torch.bfloat16) | |
| self.bias = torch.randn((n,), device=self.device, dtype=torch.bfloat16) | |
| self.scale = torch.tensor([0.25], device=self.device, dtype=torch.float32) | |
| self.out = torch.empty_like(self.input, dtype=_fp8_dtype()) | |
| def _reference(self) -> torch.Tensor: | |
| y = self.input.float() + self.bias.float() | |
| y = torch.nn.functional.gelu(y, approximate="tanh") | |
| limit = _fp8_max() | |
| y = torch.clamp(y / self.scale.float(), -limit, limit) | |
| return y.to(_fp8_dtype()) | |
| def setup_decode_m1(self) -> None: | |
| self._setup_shape(1, 4096) | |
| def benchmark_decode_m1(self) -> None: | |
| self.kernel.bias_gelu_quantize_fp8_static_bf16( | |
| self.input, self.bias, self.scale, out=self.out | |
| ) | |
| def verify_decode_m1(self) -> torch.Tensor: | |
| return self._reference() | |
| def setup_decode_m8(self) -> None: | |
| self._setup_shape(8, 4096) | |
| def benchmark_decode_m8(self) -> None: | |
| self.kernel.bias_gelu_quantize_fp8_static_bf16( | |
| self.input, self.bias, self.scale, out=self.out | |
| ) | |
| def verify_decode_m8(self) -> torch.Tensor: | |
| return self._reference() | |
| def setup_small_m16(self) -> None: | |
| self._setup_shape(16, 4096) | |
| def benchmark_small_m16(self) -> None: | |
| self.kernel.bias_gelu_quantize_fp8_static_bf16( | |
| self.input, self.bias, self.scale, out=self.out | |
| ) | |
| def verify_small_m16(self) -> torch.Tensor: | |
| return self._reference() | |
| def setup_prefill_m64(self) -> None: | |
| self._setup_shape(64, 4096) | |
| def benchmark_prefill_m64(self) -> None: | |
| self.kernel.bias_gelu_quantize_fp8_static_bf16( | |
| self.input, self.bias, self.scale, out=self.out | |
| ) | |
| def verify_prefill_m64(self) -> torch.Tensor: | |
| return self._reference() | |
| def setup_prefill_m128(self) -> None: | |
| self._setup_shape(128, 4096) | |
| def benchmark_prefill_m128(self) -> None: | |
| self.kernel.bias_gelu_quantize_fp8_static_bf16( | |
| self.input, self.bias, self.scale, out=self.out | |
| ) | |
| def verify_prefill_m128(self) -> torch.Tensor: | |
| return self._reference() | |
| def setup_wide_n8192_m16(self) -> None: | |
| self._setup_shape(16, 8192) | |
| def benchmark_wide_n8192_m16(self) -> None: | |
| self.kernel.bias_gelu_quantize_fp8_static_bf16( | |
| self.input, self.bias, self.scale, out=self.out | |
| ) | |
| def verify_wide_n8192_m16(self) -> torch.Tensor: | |
| return self._reference() | |
| def setup_wide_n8192_m128(self) -> None: | |
| self._setup_shape(128, 8192) | |
| def benchmark_wide_n8192_m128(self) -> None: | |
| self.kernel.bias_gelu_quantize_fp8_static_bf16( | |
| self.input, self.bias, self.scale, out=self.out | |
| ) | |
| def verify_wide_n8192_m128(self) -> torch.Tensor: | |
| return self._reference() | |
| def _register_bias_gelu_shapes() -> None: | |
| for label, m, n in QUANT_SHAPES: | |
| def setup(self, m=m, n=n) -> None: | |
| self._setup_shape(m, n) | |
| def benchmark(self) -> None: | |
| self.kernel.bias_gelu_quantize_fp8_static_bf16( | |
| self.input, self.bias, self.scale, out=self.out | |
| ) | |
| def verify(self) -> torch.Tensor: | |
| return self._reference() | |
| setattr(BiasGeluFp8QuantizeBenchmark, f"setup_{label}", setup) | |
| setattr(BiasGeluFp8QuantizeBenchmark, f"benchmark_{label}", benchmark) | |
| setattr(BiasGeluFp8QuantizeBenchmark, f"verify_{label}", verify) | |
| class GeluFp8QuantizeBenchmark(Benchmark): | |
| seed = 3 | |
| def _setup_shape(self, m: int, n: int) -> None: | |
| self.input = torch.randn((m, n), device=self.device, dtype=torch.bfloat16) | |
| self.scale = torch.tensor([0.25], device=self.device, dtype=torch.float32) | |
| self.out = torch.empty_like(self.input, dtype=_fp8_dtype()) | |
| def _reference(self) -> torch.Tensor: | |
| y = torch.nn.functional.gelu(self.input.float(), approximate="tanh") | |
| limit = _fp8_max() | |
| y = torch.clamp(y / self.scale.float(), -limit, limit) | |
| return y.to(_fp8_dtype()) | |
| def setup_decode_m1(self) -> None: | |
| self._setup_shape(1, 4096) | |
| def benchmark_decode_m1(self) -> None: | |
| self.kernel.gelu_quantize_fp8_static_bf16( | |
| self.input, self.scale, out=self.out | |
| ) | |
| def verify_decode_m1(self) -> torch.Tensor: | |
| return self._reference() | |
| def setup_decode_m8(self) -> None: | |
| self._setup_shape(8, 4096) | |
| def benchmark_decode_m8(self) -> None: | |
| self.kernel.gelu_quantize_fp8_static_bf16( | |
| self.input, self.scale, out=self.out | |
| ) | |
| def verify_decode_m8(self) -> torch.Tensor: | |
| return self._reference() | |
| def setup_small_m16(self) -> None: | |
| self._setup_shape(16, 4096) | |
| def benchmark_small_m16(self) -> None: | |
| self.kernel.gelu_quantize_fp8_static_bf16( | |
| self.input, self.scale, out=self.out | |
| ) | |
| def verify_small_m16(self) -> torch.Tensor: | |
| return self._reference() | |
| def setup_prefill_m64(self) -> None: | |
| self._setup_shape(64, 4096) | |
| def benchmark_prefill_m64(self) -> None: | |
| self.kernel.gelu_quantize_fp8_static_bf16( | |
| self.input, self.scale, out=self.out | |
| ) | |
| def verify_prefill_m64(self) -> torch.Tensor: | |
| return self._reference() | |
| def setup_prefill_m128(self) -> None: | |
| self._setup_shape(128, 4096) | |
| def benchmark_prefill_m128(self) -> None: | |
| self.kernel.gelu_quantize_fp8_static_bf16( | |
| self.input, self.scale, out=self.out | |
| ) | |
| def verify_prefill_m128(self) -> torch.Tensor: | |
| return self._reference() | |
| def setup_wide_n8192_m16(self) -> None: | |
| self._setup_shape(16, 8192) | |
| def benchmark_wide_n8192_m16(self) -> None: | |
| self.kernel.gelu_quantize_fp8_static_bf16( | |
| self.input, self.scale, out=self.out | |
| ) | |
| def verify_wide_n8192_m16(self) -> torch.Tensor: | |
| return self._reference() | |
| def setup_wide_n8192_m128(self) -> None: | |
| self._setup_shape(128, 8192) | |
| def benchmark_wide_n8192_m128(self) -> None: | |
| self.kernel.gelu_quantize_fp8_static_bf16( | |
| self.input, self.scale, out=self.out | |
| ) | |
| def verify_wide_n8192_m128(self) -> torch.Tensor: | |
| return self._reference() | |
| def _register_gelu_shapes() -> None: | |
| for label, m, n in QUANT_SHAPES: | |
| def setup(self, m=m, n=n) -> None: | |
| self._setup_shape(m, n) | |
| def benchmark(self) -> None: | |
| self.kernel.gelu_quantize_fp8_static_bf16( | |
| self.input, self.scale, out=self.out | |
| ) | |
| def verify(self) -> torch.Tensor: | |
| return self._reference() | |
| setattr(GeluFp8QuantizeBenchmark, f"setup_{label}", setup) | |
| setattr(GeluFp8QuantizeBenchmark, f"benchmark_{label}", benchmark) | |
| setattr(GeluFp8QuantizeBenchmark, f"verify_{label}", verify) | |
| _register_bias_gelu_shapes() | |
| _register_gelu_shapes() | |