Skip to content

optimize triton ops to improve performance - #398

Closed
MichelleWu351 wants to merge 2 commits into
XPU-Forces:hw/950-perffrom
MichelleWu351:hw/950-perf-triton-ops-optimization
Closed

MichelleWu351 wants to merge 2 commits into
XPU-Forces:hw/950-perffrom
MichelleWu351:hw/950-perf-triton-ops-optimization

Conversation

@MichelleWu351

Copy link
Copy Markdown
Contributor

No description provided.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces significant performance optimizations and refactorings across various Triton kernels (including fused add RMSNorm, GELU, LayerNorm, SDPA, and Vision RoPE) to improve NPU hardware utilization, such as adding single-pass paths, instruction reordering, and parallelizing vector/cube computations. The review feedback highlights critical issues that need to be addressed: marking dynamic dimensions (like n_rows and task counts) as tl.constexpr will trigger frequent recompilations and latency spikes during LLM serving; a duplicate definition of gelu_tanh_approx in gelu.py creates dead code; hardcoding a small block size in vision_rope.py degrades performance; and a potential division-by-zero in sdpa.py requires a safe division pattern.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +66 to +68
RSTD_row_stride: tl.constexpr,
n_rows: tl.constexpr,
n_cols: tl.constexpr,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Marking n_rows as tl.constexpr forces Triton to recompile the kernel whenever the number of rows (which is highly dynamic during LLM serving due to varying batch sizes and sequence lengths) changes. This can lead to severe compilation overhead and latency spikes. Since n_rows is only used for loop bounds and masking, it should be passed as a regular runtime argument.

Suggested change
RSTD_row_stride: tl.constexpr,
n_rows: tl.constexpr,
n_cols: tl.constexpr,
RSTD_row_stride: tl.constexpr,
n_rows,
n_cols: tl.constexpr,

Comment on lines +263 to +265
RSTD_row_stride: tl.constexpr,
n_rows: tl.constexpr,
n_cols: tl.constexpr,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Marking n_rows as tl.constexpr forces Triton to recompile the kernel whenever the number of rows (which is highly dynamic during LLM serving due to varying batch sizes and sequence lengths) changes. This can lead to severe compilation overhead and latency spikes. Since n_rows is only used for loop bounds and masking, it should be passed as a regular runtime argument.

Suggested change
RSTD_row_stride: tl.constexpr,
n_rows: tl.constexpr,
n_cols: tl.constexpr,
RSTD_row_stride: tl.constexpr,
n_rows,
n_cols: tl.constexpr,

Comment on lines +99 to +101
stride_row: tl.constexpr,
n_rows: tl.constexpr,
n_cols: tl.constexpr,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Marking n_rows as tl.constexpr forces Triton to recompile the kernel whenever the number of rows (which is highly dynamic during LLM serving due to varying batch sizes and sequence lengths) changes. This can lead to severe compilation overhead and latency spikes. Since n_rows is only used for loop bounds and masking, it should be passed as a regular runtime argument.

Suggested change
stride_row: tl.constexpr,
n_rows: tl.constexpr,
n_cols: tl.constexpr,
stride_row: tl.constexpr,
n_rows,
n_cols: tl.constexpr,

filter_value: tl.constexpr,
k: tl.constexpr,
TOTAL_TASKS,
TOTAL_TASKS: tl.constexpr,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Marking TOTAL_TASKS as tl.constexpr forces Triton to recompile the kernel whenever the total number of tasks (which depends on the dynamic batch size) changes. This can lead to severe compilation overhead and latency spikes. Since TOTAL_TASKS is only used as a loop bound, it should be passed as a regular runtime argument.

Suggested change
TOTAL_TASKS: tl.constexpr,
TOTAL_TASKS,

GROUP_CHUNKS: tl.constexpr,
BLOCK_SIZE: tl.constexpr,
DESCENDING: tl.constexpr,
MERGE_TOTAL_TASKS: tl.constexpr,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Marking MERGE_TOTAL_TASKS as tl.constexpr forces Triton to recompile the kernel whenever the total number of merge tasks (which depends on the dynamic batch size) changes. This can lead to severe compilation overhead and latency spikes. Since MERGE_TOTAL_TASKS is only used as a loop bound, it should be passed as a regular runtime argument.

Suggested change
MERGE_TOTAL_TASKS: tl.constexpr,
MERGE_TOTAL_TASKS,

block_m = block_m_1
block_l = block_l_1

block_o = block_o / block_l[:, None]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

To prevent division by zero and potential NaN propagation when all elements in a row are masked out (which makes block_l zero), use a safe division pattern. This aligns with the repository's general rules for safe division in Triton kernels.

Suggested change
block_o = block_o / block_l[:, None]
safe_l = tl.where(block_l > 0, block_l, 1.0)
block_o = tl.where(block_l[:, None] > 0, block_o / safe_l[:, None], 0.0)
References
  1. In Triton kernels, prevent division by zero when a denominator like l_i (sum of probabilities) can be zero due to masking. Use a safe division pattern, for example by dividing by tl.where(l_i > 0, l_i, 1.0) and then setting the result to zero where l_i was zero.

Comment on lines +34 to +41
@triton.jit
def gelu_tanh_approx(x):
"""GELU activation using exp (iter_2 optimization, kept unchanged)."""
c = 1.5957691216057308 # 2 * sqrt(2/π)
k = 0.07135889030264642 # c * 0.044715,预计算常量
x_sq = x * x
inner = x * (c + k * x_sq)
return x / (1 + tl.math.exp(-inner))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There are two consecutive definitions of gelu_tanh_approx (the first on lines 25-31 and the second on lines 34-41). The second definition completely overrides the first one in Python's namespace, making the first one dead code. Please remove the duplicate/overridden definition or rename them if both are intended to be kept.

cast_to_fp32 = q.dtype != torch.float32

token_block_size = _get_token_block_size(n_qh, n_kh)
token_block_size = 2

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Hardcoding token_block_size = 2 makes the helper function _get_token_block_size dead code and can significantly hurt memory coalescing and vectorization efficiency on the NPU. A block size of 2 in the token dimension is extremely small. Consider keeping the dynamic block size selection or using a larger power-of-two block size (e.g., 16 or 32) for better hardware utilization.

@MichelleWu351
MichelleWu351 force-pushed the hw/950-perf-triton-ops-optimization branch from 310d87d to 4ee7bcd Compare July 15, 2026 01:12
@shengw-bd

Copy link
Copy Markdown
Collaborator

These optimizations have already been reworked and merged into hw/950-perf, and then landed in master through #454. This PR can be closed as superseded.

@shengw-bd shengw-bd closed this Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants