Kernels
File size: 7,710 Bytes
e873e70
 
 
 
 
 
 
 
 
 
 
 
 
 
f30427a
e873e70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a6e5c43
 
f30427a
 
 
 
 
 
 
 
a6e5c43
 
 
f30427a
 
 
 
a6e5c43
 
 
 
 
 
 
f30427a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e873e70
f30427a
e873e70
a6e5c43
 
 
 
 
f30427a
 
 
 
 
 
 
 
a6e5c43
 
 
 
 
e873e70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a7f6a13
 
 
 
 
 
f30427a
a7f6a13
 
 
 
 
 
f30427a
 
 
 
 
 
e873e70
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
---
library_name: kernels
license: apache-2.0
---

This is the repository card of `SuperexponentialAI/relu`. It was built to
be used with the [`kernels` library](https://github.com/huggingface/kernels).

## How to use

```python
# make sure `kernels` is installed: `pip install -U kernels`
from kernels import get_kernel

kernel_module = get_kernel("SuperexponentialAI/relu", version=3)
relu = kernel_module.relu

relu(x)
```

## Available functions

- `relu`

## Scope

This build covers **cpu, cuda, and xpu only**. `metal` and `rocm` are
declared in `kernels-community/relu` upstream but are intentionally
**not** included here β€” no Apple or AMD hardware was available to build
or validate them, and this repo only ships backends that were actually
optimized and benchmarked.

Each included backend supports **fp32, fp16, bf16, and int8** (upstream
`kernels-community/relu` is fp32-only). Semantics match upstream exactly,
including `NaN β†’ 0` (not PyTorch's `NaN β†’ NaN`) β€” this is a pre-existing
upstream behavior, intentionally preserved. All backends verified
bit-identical to `torch.nn.functional.relu` on non-NaN inputs.

## Optimizations

### Results at a glance

GPU rows: nsys GPU-kernel duration or the official harness with matched
buffer handling, 3+ passes, correctness-gated (bit-identical to
`F.relu`). Upstream (`kernels-community/relu`) is fp32-only, so other
dtypes have no Hub baseline. **v3 corrects earlier 4090 claims** (fp16/
bf16 "1.85x/1.81x", fp32 "1.20x DRAM") that came from a position-biased
shared-buffer interleave, and fixes a real (32 MiB, L2] launch-config
cliff β€” full story in `L2_BAND_CLIFF.md`; methodology in
`PERFORMANCE.md`.

| target | dtype | vs torch | vs upstream Hub |
|---|---|---|---|
| RTX 4090 (sm_89) | fp32 | ~parity (0.95–1.09x) | 0.96–1.22x L2, parity DRAM |
| RTX 4090 | fp16 / bf16 | 1.17–1.27x base, ~parity large | β€” |
| RTX 4090 | int8 | **1.14–1.37x** | β€” |
| H100 (sm_90) | fp32 | **1.52x** L2, ~parity DRAM | **1.24–1.44x** DRAM |
| H100 | fp16 / bf16 | **1.38x** L2, ~1.0–1.20x DRAM | β€” |
| H100 | int8 | **1.23–1.61x** | β€” |
| CPU (i9-13900K) | fp32/fp16/bf16/int8 | at DRAM bandwidth ceiling | β€” |
| XPU (UHD 770) | fp32/fp16/bf16/int8 | 1.01x / 0.96x / 1.16x / 1.06x | β€” |

### CUDA (sm_70–sm_90, benchmarked on RTX 4090 / Ada and H100 / Hopper)

float4-vectorized, flat grid-stride, scalar tail, arch-adaptive launch:
128-thread blocks below 32 MiB working sets, 512 above; streaming
`__ldcs`/`__stcs` **except** in the pre-Hopper (32 MiB, L2] band, which
uses default loads + streaming stores (v3 fix β€” evict-first loads there
ran 0.34–0.65x vs torch by discarding L2 input residency; see
`L2_BAND_CLIFF.md`), and Hopper+ below 16 MB, which uses unroll-2 /
stream-store-only / 256-thread blocks (+4.6–9.3%, symmetric pairwise
A/B). int8 additionally uses `__vmaxs4` SIMD byte-max. Tuned via
per-arch empirical sweeps, a 5-agent design fan-out, and roofline
analysis (`OPTIMIZATION.md` for sm_89, `H100_BENCHMARK.md` for sm_90 β€”
including which standalone-sweep "wins" failed in-harness verification
and were not shipped).

- **4090 vs `torch.relu`** (v3, fair buffer handling β€” see
  `L2_BAND_CLIFF.md` for why v2's shared-buffer interleave numbers were
  retracted): fp32 ~parity at every size (0.95–1.09x, both at the ~944
  GB/s DRAM wall when DRAM-bound); fp16/bf16 1.17–1.27x at 1024Β²,
  ~parity at 4096Β²; int8 1.14–1.37x. In the band the v2 kernel lost
  2–3x, v3 measures 0.99–1.06x.
- **4090 vs upstream `kernels-community/relu`** (fp32, bit-identical
  output): 0.96–1.22x at L2-resident sizes (run-sensitive), parity at
  the DRAM wall β€” both kernels saturate GDDR6X there. Upstream's real
  gaps are dtype coverage (fp32-only) and the 1-D launch collapse
  below.
- fp16/bf16/fp8/int8 element throughput scales with the memory-bound
  1/sizeof(dtype) rule: bf16/fp16 β‰ˆ 2x fp32, int8/fp8 β‰ˆ 4x fp32
  intrinsically (`DTYPE_THROUGHPUT.md`).

**H100 80GB HBM3 (sm_90)** β€” same method (nsys GPU-kernel duration,
interleaved 1:1, 3 independent passes, `H100_BENCHMARK.md`):

- DRAM-bound, this kernel runs at the HBM3 wall (~3.0 TB/s, ~90% of
  peak). The upstream Hub kernel never reaches it (2.2–2.4 TB/s), so
  the DRAM-bound margin is real and position-insensitive: **1.24–1.44x
  vs upstream** (fp32 4096Β²/8192Β²).
- vs `torch` (separate-buffer symmetric pairs): fp32 **1.52x** at
  L2-resident 1024Β², ~parity DRAM-bound (both at the wall); fp16/bf16
  **1.38x** at 1024Β², 1.0–1.20x at 4096Β²; int8 **1.23x** at 1024Β²,
  **1.61x** at L2-resident 4096Β². The pre-Hopper L2-band cliff does not
  occur on Hopper (measured 1.43–1.55x over torch at band sizes with
  the streaming config; `L2_BAND_CLIFF.md`).
- Robustness: this kernel's launch is shape-agnostic. The upstream Hub
  kernel launches `grid = numel/size(-1)` blocks, which collapses to a
  single block on flat 1-D tensors β€” measured **140x slower** than this
  kernel at 4096Β² elements on H100 (`relu(x.view(-1))`-shaped calls).

### CPU (benchmarked on i9-13900K)

Rewritten with AVX2, OpenMP, and non-temporal stores; extended to
fp16/bf16/int8. A thread/ILP sweep confirmed the implementation sits at
the memory-bandwidth ceiling rather than being compute- or
thread-count-limited.

### XPU (SYCL, validated on Intel UHD 770 iGPU)

Vectorized to 16 bytes/work-item for coalesced access, extended to
fp16/bf16/int8. Hits the DDR5 bandwidth wall on all dtypes tested;
int8 measured 2.6x the naive (non-vectorized) SYCL implementation.

**Live comparison vs `torch.relu`** (torch 2.12.0+xpu, Intel UHD 770 β€”
a consumer iGPU, not an officially-supported PyTorch XPU tier; both
implementations are bound by the same shared-DDR5 wall, so gains are
modest compared to CUDA/CPU):

| dtype | torch (GB/s) | ours (GB/s) | ratio (ours vs torch) |
|-------|:---:|:---:|:---:|
| fp32  | 40.6 | 40.8 | 1.01x (tied) |
| fp16  | 43.8 | 42.1 | 0.96x (torch ~4% faster) |
| bf16  | 36.6 | 42.5 | 1.16x faster |
| int8  | 78.0 | 82.9 | 1.06x faster |

All four dtypes verified bit-identical to `F.relu`. See `AITESTING.md`
for the environment setup and hardware-driver caveats needed to run
this (a separate `torch==2.12.0+xpu` venv, Level Zero runtime install,
device ACLs, and a CPU-generate-then-copy workaround for an on-device
fp16/bf16 creation bug on this GPU).

## Benchmarks

Official-harness scripts live in `benchmarks/`: `ReluBenchmark` mirrors
upstream's fp32 base/large workloads (directly comparable), and
`ReluDtypeBenchmark` adds the fp16/bf16/int8 workloads upstream lacks.

- Local checkout: `kernels benchmark ./relu-build` (all workloads verify
  against `F.relu`).
- Remote (`kernels benchmark SuperexponentialAI/relu --version 3`)
  requires this repo to be hosted as a `kernel`-type repo; it is
  currently `model`-type (kernel-repo creation is restricted for this
  account), so use the local form until it migrates. The same caveat
  applies to the `get_kernel` snippet above β€” load via
  `snapshot_download` + `sys.path` in the meantime.

`ReluDtypeBenchmark` uses the kernel's preallocated `out=` form and times
the reference the same way β€” the allocating form alternates two live
output blocks and pushes L2-boundary workloads off the L2 cliff for
whichever side allocates (details in `L2_BAND_CLIFF.md`). For pure GPU
kernel time, the nsys numbers above remain the ground truth
(`INVESTIGATION_L2.md`).

Full methodology and results: see `OPTIMIZATION.md`, `DTYPE_THROUGHPUT.md`,
and `INVESTIGATION_L2.md` in this repository.

## Upstream

The original source code for this kernel comes from
[kernels-community/relu](https://huggingface.co/kernels-community/relu).