Post-Operations - Post-Operations - 5.3 English - 57404

AOCL User Guide (57404)

Document_ID
57404
Release_Date
2026-05-13
Version
5.3 English

Post-operations allow you to fuse additional computations with GEMM operations, reducing memory bandwidth and improving performance. The effective computation becomes:

C = post_ops( alpha * op(A) * op(B) + beta * C )

All post-operations are configured through a single dlp_metadata_t struct passed as the last argument to any GEMM function. Pass NULL when no post-ops are needed. Up to AOCL_MAX_POST_OPS (8) post-operations can be chained.

For complete API reference, see dlp_metadata_t and the Post-Operations Guide Wiki.

Post-Op Types:

Type

Description

BIAS

Adds a 1D bias vector (length n) to each row of the output

ELTWISE

Applies an element-wise activation function

SCALE

Per-channel or per-tensor scaling with optional zero-point

MATRIX_ADD

Element-wise addition of another matrix to the output

MATRIX_MUL

Element-wise multiplication of the output with another matrix

Supported Activation Functions (ELTWISE):

DLP_ELT_ALGO_TYPE

Formula

Parameters

RELU

max(0, x)

None

PRELU

x >= 0 ? x : alpha * x

alpha: leak factor

GELU_TANH

GELU with tanh approximation

None

GELU_ERF

GELU with erf approximation

None

CLIP

clamp(x, alpha, beta)

alpha: min, beta: max

SWISH

x * sigmoid(alpha * x)

alpha: scaling

TANH

tanh(x)

None

SIGMOID

1 / (1 + exp(-x))

None

Key Metadata Fields:

Field

Type

Description

seq_length

md_t

Number of post-operations to apply

seq_vector

DLP_POST_OP_TYPE*

Array defining the order of post-ops

bias

dlp_post_op_bias*

Bias parameters (when BIAS is in sequence)

eltwise

dlp_post_op_eltwise*

Eltwise/activation parameters

scale

dlp_scale_t*

Scale + zero-point parameters

matrix_add

dlp_post_op_matrix_add*

Matrix addition parameters

matrix_mul

dlp_post_op_matrix_mul*

Matrix multiplication parameters

num_eltwise

md_t

Number of eltwise operations (when chaining multiple)

Example: Bias + ReLU Activation:

float bias_values[N] = { /* ... */ };

dlp_post_op_bias bias_op = {
    .bias = bias_values, .stor_type = DLP_F32,
    .sf = NULL, .zp = NULL
};

dlp_post_op_eltwise relu_op = {
    .sf = NULL,
    .algo = { .alpha = NULL, .beta = NULL,
              .algo_type = RELU, .stor_type = DLP_F32 }
};

DLP_POST_OP_TYPE seq[] = { BIAS, ELTWISE };

dlp_metadata_t meta = {0};
meta.seq_length  = 2;
meta.seq_vector  = seq;
meta.bias        = &bias_op;
meta.eltwise     = &relu_op;
meta.num_eltwise = 1;

aocl_gemm_f32f32f32of32('R', 'N', 'N', m, n, k,
    1.0f, a, lda, 'N', b, ldb, 'N',
    0.0f, c, ldc, &meta);

Example: MATRIX_ADD (Residual Connection):

float residual[M * N] = { /* ... */ };

dlp_post_op_matrix_add add_op = {
    .matrix    = residual,
    .ldm       = n,
    .stor_type = DLP_F32,
    .sf        = NULL
};

DLP_POST_OP_TYPE seq[] = { MATRIX_ADD };

dlp_metadata_t meta = {0};
meta.seq_length = 1;
meta.seq_vector = seq;
meta.matrix_add = &add_op;

aocl_gemm_f32f32f32of32('R', 'N', 'N', m, n, k,
    1.0f, a, lda, 'N', b, ldb, 'N',
    0.0f, c, ldc, &meta);

Example: PRELU with Alpha Parameter:

float alpha_val = 0.01f;

dlp_post_op_eltwise prelu_op = {
    .sf   = NULL,
    .algo = { .alpha = &alpha_val, .beta = NULL,
              .algo_type = PRELU, .stor_type = DLP_F32 }
};

DLP_POST_OP_TYPE seq[] = { ELTWISE };

dlp_metadata_t meta = {0};
meta.seq_length  = 1;
meta.seq_vector  = seq;
meta.eltwise     = &prelu_op;
meta.num_eltwise = 1;

Tip

  • Always zero-initialize metadata: dlp_metadata_t meta = {0};

  • Align bias, scale, and residual buffers to 64-byte boundaries for best performance.

  • Ensure stor_type matches the accumulator type of your GEMM variant.