Skip to main content

Overview

The epilogue is the final stage of a GEMM or convolution kernel that processes the accumulated result before writing to output memory. CUTLASS provides a flexible system for customizing epilogue operations through template-based functors.
The epilogue allows you to fuse additional operations (activation functions, bias addition, etc.) directly into the GEMM/convolution kernel, eliminating separate kernel launches and memory bandwidth overhead.

Standard Epilogue: Linear Combination

The default epilogue performs a linear combination:

LinearCombination Template

include/cutlass/epilogue/thread/linear_combination.h:58

Template Parameters

typename
Data type for output tensor D (e.g., float, cutlass::half_t)
int
Number of elements processed per operation (vectorization factor)Typically 128 / sizeof_bits<ElementOutput_> for optimal memory bandwidth
typename
default:"ElementOutput_"
Data type of the accumulated result from the main loop
typename
default:"ElementOutput_"
Data type used for alpha/beta computation (often higher precision)
ScaleType::Kind
default:"ScaleType::Default"
Scaling behavior:
  • ScaleType::Default - Standard alpha/beta scaling
  • ScaleType::NoBetaScaling - Beta is always 0
  • ScaleType::OnlyAlphaScaling - Only alpha scaling, no beta term
FloatRoundStyle
default:"round_to_nearest"
Rounding mode for type conversions

Params Structure

include/cutlass/epilogue/thread/linear_combination.h:89
ElementCompute
Scalar multiplier for the accumulator
ElementCompute
Scalar multiplier for the source tensor C
ElementCompute const*
Pointer to alpha in device memory (enables per-problem alpha)
ElementCompute const*
Pointer to beta in device memory

Activation Function Epilogues

CUTLASS provides epilogues with fused activation functions:

ReLU

include/cutlass/epilogue/thread/linear_combination_relu.h
Computes: D = max(0, alpha * accumulator + beta * C)

GELU

include/cutlass/epilogue/thread/linear_combination_gelu.h
Computes: D = x * 0.5 * (1 + tanh(sqrt(2/π) * (x + 0.044715 * x³))) where x = alpha * accumulator + beta * C

Sigmoid

include/cutlass/epilogue/thread/linear_combination_sigmoid.h
Computes: D = sigmoid(alpha * accumulator + beta * C) = 1 / (1 + exp(-x))

SiLU (Swish)

include/cutlass/epilogue/thread/linear_combination_silu.h
Computes: D = x * sigmoid(x) where x = alpha * accumulator + beta * C

Hardswish

include/cutlass/epilogue/thread/linear_combination_hardswish.h
Computes: D = x * ReLU6(x + 3) / 6 where x = alpha * accumulator + beta * C

Leaky ReLU

include/cutlass/epilogue/thread/linear_combination_leaky_relu.h
Computes: D = x > 0 ? x : leaky_alpha * x where x = alpha * accumulator + beta * C

Bias Addition

Linear Combination with Bias

include/cutlass/epilogue/thread/linear_combination_bias_elementwise.h
This epilogue adds a per-channel bias vector before applying an activation.

Params Structure for Bias

Clamping Operations

Linear Combination with Clamp

include/cutlass/epilogue/thread/linear_combination_clamp.h
Computes: D = clamp(alpha * accumulator + beta * C, min_value, max_value)

Complete GEMM Example with Epilogue

From examples/12_gemm_bias_relu/gemm_bias_relu.cu:

Broadcasting and Reduction Epilogues

Tensor Broadcast

include/cutlass/epilogue/thread/linear_combination_tensor_broadcast.hpp
Enables broadcasting operations like adding a bias vector along specific dimensions.

Planar Complex Epilogues

For complex-valued GEMM with planar (split real/imaginary) storage:
include/cutlass/epilogue/thread/linear_combination_planar_complex.h

Generic Epilogue with Custom Operations

LinearCombinationGeneric

include/cutlass/epilogue/thread/linear_combination_generic.h
Allows specifying custom activation functors:
Custom Activation

Per-Channel vs Per-Tensor Scaling

Per-Tensor (Default)

Per-Channel (Blockwise)

Epilogue Visitor Pattern (CUTLASS 3.x)

CUTLASS 3.x introduces a visitor-based epilogue for maximum flexibility:
Epilogue Visitor

Performance Considerations

Vectorization

Set Count to maximize vectorized memory access (typically 128 bits / element size)

Register Pressure

Complex epilogues increase register usage - may reduce occupancy

Compute vs Memory

Epilogue fusion is beneficial when compute cost is much less than memory bandwidth

Type Conversion

Be mindful of precision when ElementAccumulator ≠ ElementOutput

Available Epilogue Types

LinearCombination

Standard D = α * acc + β * C

LinearCombinationRelu

With ReLU: D = max(0, α * acc + β * C)

LinearCombinationGELU

With GELU activation

LinearCombinationSigmoid

With Sigmoid activation

LinearCombinationSilu

With SiLU (Swish) activation

LinearCombinationBiasRelu

With bias addition and ReLU

LinearCombinationClamp

With min/max clamping

LinearCombinationGeneric

Custom user-defined activation

Common Patterns

No Source Tensor (β = 0)

In-Place Operation (D = C)

Accumulation Mode (α = 1, β = 1)

See Also

GEMM API

Learn how epilogues integrate with GEMM kernels

Convolution API

Epilogues work the same way for convolutions

Custom Kernels

Examples of custom epilogue implementations

Fusion Techniques

Performance optimization through operation fusion