Row-parallel online softmax. One program per row.
(
input_ptr,
output_ptr,
n_cols,
stride_input_row,
stride_output_row,
BLOCK_SIZE: tl.constexpr,
)
| 18 | |
| 19 | @triton.jit |
| 20 | def softmax_kernel( |
| 21 | input_ptr, |
| 22 | output_ptr, |
| 23 | n_cols, |
| 24 | stride_input_row, |
| 25 | stride_output_row, |
| 26 | BLOCK_SIZE: tl.constexpr, |
| 27 | ): |
| 28 | """Row-parallel online softmax. One program per row.""" |
| 29 | row_idx = tl.program_id(0) |
| 30 | |
| 31 | row_start_input = input_ptr + row_idx * stride_input_row |
| 32 | row_start_output = output_ptr + row_idx * stride_output_row |
| 33 | |
| 34 | col_offsets = tl.arange(0, BLOCK_SIZE) |
| 35 | mask = col_offsets < n_cols |
| 36 | |
| 37 | # Load row |
| 38 | row = tl.load(row_start_input + col_offsets, mask=mask, other=float("-inf")) |
| 39 | |
| 40 | # Numerically stable softmax: subtract max |
| 41 | row_max = tl.max(row, axis=0) |
| 42 | row = row - row_max |
| 43 | |
| 44 | # Exponentiate |
| 45 | numerator = tl.exp(row) |
| 46 | |
| 47 | # Sum |
| 48 | denominator = tl.sum(numerator, axis=0) |
| 49 | |
| 50 | # Divide |
| 51 | result = numerator / denominator |
| 52 | |
| 53 | # Store |
| 54 | tl.store(row_start_output + col_offsets, result, mask=mask) |
| 55 | |
| 56 | |
| 57 | def kernel_fn(x: torch.Tensor) -> torch.Tensor: |
nothing calls this directly
no outgoing calls
no test coverage detected