Skip to content

Add one-level RMSNorm kernel with tiling harness and precision check. - #26

Open
wangyuascend-spec wants to merge 5 commits into
PTO-ISA:mainfrom
wangyuascend-spec:add-one-level-rms-norm
Open

Add one-level RMSNorm kernel with tiling harness and precision check.#26
wangyuascend-spec wants to merge 5 commits into
PTO-ISA:mainfrom
wangyuascend-spec:add-one-level-rms-norm

Conversation

@wangyuascend-spec

Copy link
Copy Markdown

Introduce fp16 RMSNorm (fp32 compute) under one-level-arch, with tiling_info specified in the harness and scripts to generate/compare golden outputs.

Introduce fp16 RMSNorm (fp32 compute) under one-level-arch, with tiling_info
specified in the harness and scripts to generate/compare golden outputs.

Co-authored-by: Cursor <cursoragent@cursor.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ac0c5f6919

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

template <typename TileVec>
inline void rsqrt_newton(TileVec &out, TileVec &a) {
TileVec x, t1, t2;
TRECIP(x, a);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Use a stable seed for rsqrt

For rows whose mean square is far from 1, this initializes the reciprocal-square-root Newton iteration with 1/a instead of a value near 1/sqrt(a). The update x *= 1.5 - 0.5*a*x*x only converges from a suitable rsqrt seed; with small activations, such as a row of 0.1s where a≈0.01, the iteration overflows or changes sign, so RMSNorm emits infinities or wildly scaled outputs even though the golden path computes a finite 1/sqrt(mean_sq + eps). Use a true rsqrt/sqrt-based seed or another stable approximation.

Useful? React with 👍 / 👎.

// const int64_t tile_n = gN;
/*以下写法能好*/
const int64_t tile_m = 1;
const int64_t tile_n = 512;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor the requested column tile size

When tiling[1]/tiling[3] describes anything other than the default 512 columns, this hard-coded tile_n makes the kernel silently process only 512 columns while still dividing the row sum by gN. For example, gN=1024 leaves the second half of each row unstored and normalizes the first half with a denominator based on only half the data; gN<512 makes TLOAD read past the logical row. Either enforce gN == tile_n == 512 up front or loop over all N tiles and accumulate the full row sum before storing.

Useful? React with 👍 / 👎.


: "${COMPILER_DIR:?Set COMPILER_DIR to the linx_blockisa_llvm_musl bin directory}"

make TESTCASE=rms_norm COMPILER_DIR="$COMPILER_DIR" DType=__half diss

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Register RMSNorm in full compile script

This per-case compile script is not reachable from the advertised benchmark/one-level-arch/compile_all.sh path: I checked that script's explicit operator list and it still omits test/kernel/normalization/rms_norm. In CI or benchmark runs that rely on the full compile script, the new kernel will never produce an ELF or get disassembled/validated, so add a compile_operator entry for this directory.

Useful? React with 👍 / 👎.

wangyuascend-spec and others added 2 commits July 31, 2026 15:27
Static RowMajor shape only accepts a data pointer; keep compile-time Valid
and avoid unsigned size_t wrap on i*gN.

Co-authored-by: Cursor <cursoragent@cursor.com>
Switch tiles/GM to dynamic Valid (-1) and construct with active dims so
tiling-driven shapes work on the register B.DIM path.

Co-authored-by: Cursor <cursoragent@cursor.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 21ba32b3e9

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +64 to +67
using tile_h = Tile<Location::Vec, dtype, tM, tN, BLayout::RowMajor, -1, -1>;
using tile_f = Tile<Location::Vec, float, tM, tN, BLayout::RowMajor, -1, -1>;
// ValidCol=1; Cols=32 → 128B PE-local (TSize min).
using tile_v = Tile<Location::Vec, float, tM, 32, BLayout::RowMajor, -1, 1>;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use static valids for one-level tile ops

With the one-level Makefile the kernel is compiled with -D__linx, and the __linx implementations of TRECIP and TROWSUM still static_assert that tile ValidRow/ValidCol are not DYNAMIC. These aliases set the RMSNorm data and vector tiles to -1 valids, so the advertised compile.all path fails as soon as TROWSUM(sqrsum, squared) or TRECIP(x, a) is instantiated instead of producing an ELF; keep the one-level tile valids static or avoid those unsupported ops for dynamic-valid tiles.

Useful? React with 👍 / 👎.

Comment on lines +19 to +20
// tiling_info: {g_m, g_n, tile_m, tile_n}
int64_t tiling_info[4] = {16, 512, 1, -1};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Read the generated tiling info

The data generator writes tiling_info.bin and exposes --g-m, --g-n, and tile arguments, but this driver always reads and computes the hard-coded 16 x 512 shape. If someone generates a non-default RMSNorm case and then runs the res_check path, the binary input size no longer matches what this code reads, and the kernel either fails the read and runs on uninitialized stack data or processes the wrong prefix with the wrong stride; load the generated tiling metadata or remove the shape options from the check path.

Useful? React with 👍 / 👎.

Handle full tiles in the main loop and the trailing ValidRow block
separately; remove early-return shape checks from the kernel.

Co-authored-by: Cursor <cursoragent@cursor.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0ae99dbba7

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".


const int64_t gM = tiling[0];
const int64_t gN = tiling[1];
const int64_t tile_m = tiling[2] > 0 ? tiling[2] : tM;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Clamp tile_m to the tile row capacity

When the tiling metadata requests tile_m > 1 (the generator exposes --tile-m and the public API documents tiling[2]), this value is passed as active_row even though all RMSNorm tile aliases are compiled with tM = 1. The dynamic-valid tile constructors do not resize the backing tile, so TLOAD/TSTORE and the elementwise ops iterate multiple rows against one row of tile storage, corrupting memory or skipping rows; either keep tile_m fixed to tM or instantiate tile types with the requested row capacity.

Useful? React with 👍 / 👎.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

1 participant