Skip to content

Triangular Inverse Kernel (continuation of Zouzias' impl)#830

Open
MirkoDeVita98 wants to merge 3 commits into
hw-native-sys:mainfrom
MirkoDeVita98:port/zouzias-pr-1
Open

Triangular Inverse Kernel (continuation of Zouzias' impl)#830
MirkoDeVita98 wants to merge 3 commits into
hw-native-sys:mainfrom
MirkoDeVita98:port/zouzias-pr-1

Conversation

@MirkoDeVita98
Copy link
Copy Markdown

@MirkoDeVita98 MirkoDeVita98 commented May 20, 2026

To reproduce:

pip install --no-build-isolation -e '.[test]'
python examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/test_triangular_inverse.py -p a2a3sim

@MirkoDeVita98 MirkoDeVita98 changed the title Triangular Inverse Kernel (continuation of Zozuias's impl) Triangular Inverse Kernel (continuation of Zouzias's impl) May 20, 2026
Copy link
Copy Markdown

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

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 a new triangular matrix inverse example, including a recursive unrolled AICore kernel, orchestration logic, and a Python test suite. It also updates the benchmark_bgemm test configuration and adds debug logging to the scene test framework. Review feedback suggests removing leftover debug print statements, correcting documentation comments about the configuration tensor layout, and simplifying the kernel dispatch function by removing redundant template parameters.

Comment thread simpler_setup/scene_test.py Outdated
Comment on lines +696 to +697
print("actual: ", actual[:10])
print("diff: ", (actual - expected).abs().mean().item())
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

These print statements appear to be leftovers from debugging and should be removed to maintain clean test output.

num_matrices = params["num_matrices"]
M = args.M.reshape(num_matrices, 1, n, n).to(torch.float16)
M_inv = linalg_inv(M)
print("M_inv (golden):", M_inv.flatten()[:10])
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

This print statement seems to be for debugging and should be removed.

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.

Let drop the print in L123.

* args[0] = M (INPUT) fp16 triangular matrices [num_matrices, N, N]
* args[1] = I_neg (INPUT) fp16 negative identity [N, N]
* args[2] = M_inv (OUTPUT) fp16 result [num_matrices, N, N]
* args[3] = config (INPUT) int64[3]: [matrix_size, num_matrices, is_lower]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The comment incorrectly states that the config tensor has 3 elements. The implementation (lines 832-835) and the test case (line 109) use 4 elements: [matrix_size, num_matrices, is_lower, block_dim]. Please update the comment to reflect the actual layout.

 *   args[3] = config (INPUT)  int64[4]: [matrix_size, num_matrices, is_lower, block_dim]
References
  1. Ensure that comments accurately reflect the code's behavior and design.

* tensor(0) = M (INPUT) fp16 triangular matrices [num_matrices * N * N]
* tensor(1) = I_neg (INPUT) fp16 negative identity [N * N]
* tensor(2) = M_inv (OUTPUT) fp16 result [num_matrices * N * N]
* tensor(3) = config (INPUT) int64[3]: [matrix_size, num_matrices, is_lower, block_dim]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The comment describes the config tensor as int64[3], but then lists 4 parameters. It should be updated to int64[4] to match the implementation and the Python test.

Suggested change
* tensor(3) = config (INPUT) int64[3]: [matrix_size, num_matrices, is_lower, block_dim]
* tensor(3) = config (INPUT) int64[4]: [matrix_size, num_matrices, is_lower, block_dim]
References
  1. Ensure that comments accurately reflect the code's behavior and design.

Comment on lines +778 to +779
template <typename InputT, typename OutputT, uint32_t NumTilesPerCubeIter, bool IsBSND>
AICORE void run_tri_inv_rec_unroll_per_num_matrices(
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The template parameters NumTilesPerCubeIter and IsBSND in run_tri_inv_rec_unroll_per_num_matrices are redundant because the function body ignores them and performs its own dispatch using literal values (1, 2, 4 for NumTilesPerCubeIter and true/false for IsBSND). These parameters should be removed from the template signature to avoid confusion and improve maintainability.

References
  1. Remove unused parameters from functions or APIs to improve code clarity and avoid misleading users.

@MirkoDeVita98 MirkoDeVita98 changed the title Triangular Inverse Kernel (continuation of Zouzias's impl) Triangular Inverse Kernel (continuation of Zouzias' impl) May 20, 2026
Comment thread Makefile Outdated
@@ -0,0 +1,8 @@

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.

Let's remove this Makefile. I used it for testing purposes (avoids excessive typing :-) )

Comment thread simpler_setup/scene_test.py Outdated
for name in output_names:
actual = getattr(test_args, name)
expected = getattr(golden_args, name)
print("actual: ", actual[:10])
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.

Let's remove this diff (it was added for debugging)

num_matrices = params["num_matrices"]
M = args.M.reshape(num_matrices, 1, n, n).to(torch.float16)
M_inv = linalg_inv(M)
print("M_inv (golden):", M_inv.flatten()[:10])
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.

Let drop the print in L123.

class TestBenchmarkBgemm(SceneTestCase):
RTOL = 1e-3
ATOL = 1e-3
RTOL = 1e-5
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.

Let revert the changes in this file to keep the MR only about the triangular inverse.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e6778622-d8e3-4644-a66a-53afdd353cc9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR introduces a complete triangular matrix inversion feature: an AICORE kernel implementing a recursive unrolled algorithm for inverting upper/lower-triangular fp16/bf16 matrices, paired with orchestration dispatch and a test suite for validation.

Changes

Triangular Inverse Feature

Layer / File(s) Summary
AICORE Infrastructure and Memory Helpers
kernel_tri_inv_rec_unroll.cpp (lines 1–237)
File header and guards; inlined BSND utilities for computing tile offsets and valid sizes for fixed and variable-length addressing; L1→L0 copy helpers for diagonal fractals and alternating block sets; auxiliary matrix preparation via pipelined TMOV/TMATMUL with explicit synchronization.
AICORE Inversion Algorithm and Kernel Orchestrator
kernel_tri_inv_rec_unroll.cpp (lines 239–731)
Single-tile inversion using inv-trick iteration loop followed by unrolled recursion with odd/even block parity swapping; main kernel TriInvRecUnrollKernel that schedules work across cube iterations and tiles, loads inputs with BSND offset support and dynamic padding, invokes per-tile inversion, and stores results with BSND-aware output sizing.
AICORE Public API and Dispatchers
kernel_tri_inv_rec_unroll.cpp (lines 732–855)
Matrix-size dispatcher runKernelTriInvRecUnroll selecting compile-time instantiations; tiles-per-iteration selector run_tri_inv_rec_unroll_per_num_matrices routing on matrix count relative to block dimension and BSND mode; simpler-framework entry point kernel_entry unpacking tensor arguments and config from buffer.
Orchestration and Task Submission
triangular_inverse_orch.cpp (lines 1–68)
Orchestration config function declaring 4 tensor arguments; entrypoint extracting input/output tensors and host config (matrix_size, num_matrices, is_lower, block_dim), logging parameters, and submitting AIC task via FUNC_TRI_INV.
Test Suite with Golden Reference Validation
test_triangular_inverse.py (lines 1–115)
Helper random_tri_matrix generating upper/lower-triangular unit-diagonal matrices; helper linalg_inv computing per-matrix inverses with added identity via NumPy; test class TestTriangularInverse building fp16 inputs and validating kernel output against reference inverses across multiple matrix sizes and orientations.

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A triangular dance, recursive and deep,
Unrolling block by block where matrices sleep,
Inv-trick loops and L0 buffers gleam bright,
From AICORE to test, the inverse shines right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main addition: a triangular inverse kernel implementation, which matches the substantial new kernel files and test infrastructure added in the changeset.
Description check ✅ Passed The description provides reproduction steps for the new kernel example, which is directly related to the added test file and kernel implementation in the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@zouzias zouzias force-pushed the port/zouzias-pr-1 branch 2 times, most recently from a108100 to d9154fd Compare May 29, 2026 06:32
@zouzias zouzias force-pushed the port/zouzias-pr-1 branch from d9154fd to 244882d Compare May 29, 2026 08:16
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/test_triangular_inverse.py (1)

91-93: ⚡ Quick win

Fix the stale matrix-construction comment.

Line 91–Line 93 say the diagonal is set to [0.5, 1.5], but this code path does not do that. Please update the comment to match the actual behavior (strictly triangular input, unit diagonal handled via + I in reference inversion).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/test_triangular_inverse.py`
around lines 91 - 93, Update the stale comment describing matrix construction to
reflect the actual behavior: note that the code builds strictly triangular fp16
matrices (zeros out the off-triangle and does not set diagonal values to
[0.5,1.5]) and that the unit diagonal is introduced only when computing the
reference inverse via "+ I" (i.e., the test uses strictly triangular input and
adds the identity in the reference inversion). Mention the
fp16/strictly-triangular inputs and the "+ I" reference inversion so future
readers understand how invertibility is handled.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/kernels/aic/kernel_tri_inv_rec_unroll.cpp`:
- Around line 765-786: The switch on matrix_size in the block that calls
runKernelTriInvRecUnroll (cases 16/32/64/128) lacks a default and thus silently
does nothing for unsupported sizes; either add a guarded default branch that
logs an error/throws/returns a failure status (ensuring M_inv is not left stale)
or validate matrix_size earlier in aicpu_orchestration_entry and fail fast with
a clear error; locate the switch using the symbol matrix_size and the
runKernelTriInvRecUnroll instantiations and implement one of these checks so
callers receive a loud, deterministic error for unsupported sizes.
- Line 23: Update the header/comment for args[3] to match the actual config
layout read by the kernel (where config values are extracted into matrix_size,
num_matrices, is_lower, block_dim); change the doc from "int64[3]: [matrix_size,
num_matrices, is_lower]" to "int64[4]: [matrix_size, num_matrices, is_lower,
block_dim]" so it accurately documents the values consumed by the code that
reads config into those four int64 variables.
- Around line 789-830: The wrapper run_tri_inv_rec_unroll_per_num_matrices
currently has unused template parameters NumTilesPerCubeIter and IsBSND; remove
them from its template parameter list so it becomes template<typename InputT,
typename OutputT> AICORE void run_tri_inv_rec_unroll_per_num_matrices(...),
leaving the internal forwards to run_tri_inv_rec_unroll(...) unchanged (those
calls still specify NumTilesPerCubeIter and IsBSND as before). Update any call
sites that instantiate run_tri_inv_rec_unroll_per_num_matrices (e.g., places
that passed <half, half, 1, false>) to drop the unused template arguments so the
wrapper is instantiated only with InputT and OutputT. Ensure symbols to edit:
run_tri_inv_rec_unroll_per_num_matrices and its callers; do not change
run_tri_inv_rec_unroll signature.
- Around line 77-89: The loop over seq_idx is unbounded and can read past
cu_seqlens via cu_seqlens[seq_idx + 1]; change the loop to be bounded by the
number of sequences (or cu_seqlens length) and handle the “not found” case:
accept an additional parameter like seq_count (or cu_seqlens_len) and iterate
using for (uint32_t seq_idx = 0; seq_idx + 1 < seq_count; ++seq_idx) (or check
seq_idx + 1 < cu_seqlens_len before indexing), keep the existing logic that
computes seq_end/seq_len/seq_num_chunks and returns when chunk_idx falls into
the range, and if the loop finishes without finding the chunk return a safe
default or error (e.g., an invalid tile info or throw/assert) to avoid
out-of-bounds reads; update all call sites of GetBSNDVarlenTileInfoFromCuSeqlens
accordingly.

In
`@examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/kernels/orchestration/triangular_inverse_orch.cpp`:
- Line 20: The argument-layout comment is using the wrong tensor index: the
config is read via orch_args.tensor(3) in this file (see uses of
orch_args.tensor(3) around the config handling), but the doc comment currently
labels it as tensor(4) and omits tensor(3); update the comment so the config
line reads "tensor(3) = config (INPUT) int64[4]: [matrix_size, num_matrices,
is_lower, block_dim]" (and ensure other tensor indices in that comment are
sequential and accurate to the orch_args.tensor(N) usages).

---

Nitpick comments:
In
`@examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/test_triangular_inverse.py`:
- Around line 91-93: Update the stale comment describing matrix construction to
reflect the actual behavior: note that the code builds strictly triangular fp16
matrices (zeros out the off-triangle and does not set diagonal values to
[0.5,1.5]) and that the unit diagonal is introduced only when computing the
reference inverse via "+ I" (i.e., the test uses strictly triangular input and
adds the identity in the reference inversion). Mention the
fp16/strictly-triangular inputs and the "+ I" reference inversion so future
readers understand how invertibility is handled.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 42bed645-9f72-456c-a3a0-2d1c29509b75

📥 Commits

Reviewing files that changed from the base of the PR and between ccb95e3 and 244882d.

📒 Files selected for processing (3)
  • examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/kernels/aic/kernel_tri_inv_rec_unroll.cpp
  • examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/kernels/orchestration/triangular_inverse_orch.cpp
  • examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/test_triangular_inverse.py

* args[0] = M (INPUT) fp16 triangular matrices [num_matrices, N, N]
* args[1] = I_neg (INPUT) fp16 negative identity [N, N]
* args[2] = M_inv (OUTPUT) fp16 result [num_matrices, N, N]
* args[3] = config (INPUT) int64[3]: [matrix_size, num_matrices, is_lower]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Stale config layout in header doc. The config is read as four int64 values (matrix_size, num_matrices, is_lower, block_dim at Lines 843-846), but this comment still describes int64[3] and omits block_dim.

📝 Proposed doc fix
- *   args[3] = config (INPUT)  int64[3]: [matrix_size, num_matrices, is_lower]
+ *   args[3] = config (INPUT)  int64[4]: [matrix_size, num_matrices, is_lower, block_dim]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* args[3] = config (INPUT) int64[3]: [matrix_size, num_matrices, is_lower]
* args[3] = config (INPUT) int64[4]: [matrix_size, num_matrices, is_lower, block_dim]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/kernels/aic/kernel_tri_inv_rec_unroll.cpp`
at line 23, Update the header/comment for args[3] to match the actual config
layout read by the kernel (where config values are extracted into matrix_size,
num_matrices, is_lower, block_dim); change the doc from "int64[3]: [matrix_size,
num_matrices, is_lower]" to "int64[4]: [matrix_size, num_matrices, is_lower,
block_dim]" so it accurately documents the values consumed by the code that
reads config into those four int64 variables.

Comment on lines +77 to +89
for (uint32_t seq_idx = 0;; ++seq_idx) {
const uint32_t seq_end = static_cast<uint32_t>(cu_seqlens[seq_idx + 1]);
const uint32_t seq_len = seq_end - seq_start;
const uint32_t seq_num_chunks = CeilDiv(seq_len, matrix_size);
if (chunk_idx < accumulated_chunks + seq_num_chunks) {
const uint32_t local_chunk_idx = chunk_idx - accumulated_chunks;
const uint32_t row_start = seq_start + local_chunk_idx * matrix_size;
const uint32_t valid_size = min(static_cast<uint32_t>(seq_end - row_start), matrix_size);
return {row_start * num_bsnd_heads * matrix_size + head_idx * matrix_size, valid_size};
}
accumulated_chunks += seq_num_chunks;
seq_start = seq_end;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find callers of the varlen helper and any non-null cu_seqlens passed in.
rg -nP --type=cpp -C3 '\bGetBSNDVarlenTileInfoFromCuSeqlens\s*\('
rg -nP --type=cpp -C2 '\bcu_seqlens\b'

Repository: hw-native-sys/simpler

Length of output: 17997


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n --hidden --no-ignore-vcs '\bcu_seqlens\b' examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/kernels/aic/kernel_tri_inv_rec_unroll.cpp
rg -n --hidden --no-ignore-vcs '\brunKernelTriInvRecUnroll\s*\(' examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example -S
rg -n --hidden --no-ignore-vcs '\brun_tri_inv_rec_unroll\s*\(' examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example -S
rg -n --hidden --no-ignore-vcs '\btriangular_inverse_orch\b' examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example -S
rg -n --hidden --no-ignore-vcs '\bcu_seqlens\s*=' examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example -S
rg -n --hidden --no-ignore-vcs '\bseqlens\b' examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example -S

Repository: hw-native-sys/simpler

Length of output: 2652


Unbounded seq_idx loop can read past cu_seqlens

  • GetBSNDVarlenTileInfoFromCuSeqlens uses a sentinel-less for (uint32_t seq_idx = 0;; ++seq_idx) while indexing cu_seqlens[seq_idx + 1]; if chunk_idx never falls into any sequence’s chunk range, the loop will keep walking past the end of cu_seqlens.
  • In this example, the varlen helper call is guarded by if (cu_seqlens != nullptr), and the dispatch APIs default cu_seqlens to nullptr, so this path is effectively dormant here; still, the helper is unsafe when reused with malformed/truncated inputs—bound the loop by passing the number of sequences / cu_seqlens length (or otherwise provide a termination condition).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/kernels/aic/kernel_tri_inv_rec_unroll.cpp`
around lines 77 - 89, The loop over seq_idx is unbounded and can read past
cu_seqlens via cu_seqlens[seq_idx + 1]; change the loop to be bounded by the
number of sequences (or cu_seqlens length) and handle the “not found” case:
accept an additional parameter like seq_count (or cu_seqlens_len) and iterate
using for (uint32_t seq_idx = 0; seq_idx + 1 < seq_count; ++seq_idx) (or check
seq_idx + 1 < cu_seqlens_len before indexing), keep the existing logic that
computes seq_end/seq_len/seq_num_chunks and returns when chunk_idx falls into
the range, and if the loop finishes without finding the chunk return a safe
default or error (e.g., an invalid tile info or throw/assert) to avoid
out-of-bounds reads; update all call sites of GetBSNDVarlenTileInfoFromCuSeqlens
accordingly.

Comment on lines +765 to +786
switch (matrix_size) {
case 16:
runKernelTriInvRecUnroll<InputT, OutputT, 16, NumTilesPerCubeIter, IsBSND>(
tensor_out, tensor_in, minus_eye_in, block_dim, num_matrices, num_bsnd_heads, is_lower, cu_seqlens
);
break;
case 32:
runKernelTriInvRecUnroll<InputT, OutputT, 32, NumTilesPerCubeIter, IsBSND>(
tensor_out, tensor_in, minus_eye_in, block_dim, num_matrices, num_bsnd_heads, is_lower, cu_seqlens
);
break;
case 64:
runKernelTriInvRecUnroll<InputT, OutputT, 64, NumTilesPerCubeIter, IsBSND>(
tensor_out, tensor_in, minus_eye_in, block_dim, num_matrices, num_bsnd_heads, is_lower, cu_seqlens
);
break;
case 128:
runKernelTriInvRecUnroll<InputT, OutputT, 128, NumTilesPerCubeIter, IsBSND>(
tensor_out, tensor_in, minus_eye_in, block_dim, num_matrices, num_bsnd_heads, is_lower, cu_seqlens
);
break;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Unsupported matrix_size silently produces no output. The switch has no default, so any matrix_size outside {16, 32, 64, 128} returns without writing M_inv, leaving stale/garbage memory with no signal. Consider validating matrix_size in aicpu_orchestration_entry (or adding a guarded default) so callers fail loudly instead of getting silently incorrect results.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/kernels/aic/kernel_tri_inv_rec_unroll.cpp`
around lines 765 - 786, The switch on matrix_size in the block that calls
runKernelTriInvRecUnroll (cases 16/32/64/128) lacks a default and thus silently
does nothing for unsupported sizes; either add a guarded default branch that
logs an error/throws/returns a failure status (ensuring M_inv is not left stale)
or validate matrix_size earlier in aicpu_orchestration_entry and fail fast with
a clear error; locate the switch using the symbol matrix_size and the
runKernelTriInvRecUnroll instantiations and implement one of these checks so
callers receive a loud, deterministic error for unsupported sizes.

Comment on lines +789 to +830
template <typename InputT, typename OutputT, uint32_t NumTilesPerCubeIter, bool IsBSND>
AICORE void run_tri_inv_rec_unroll_per_num_matrices(
__gm__ OutputT *tensor_out, __gm__ InputT *tensor_in, __gm__ InputT *minus_eye_in, uint32_t block_dim,
uint32_t matrix_size, uint32_t num_matrices, uint32_t num_bsnd_heads, uint32_t is_lower = 0,
__gm__ int32_t *cu_seqlens = nullptr
) {
if (num_bsnd_heads == 0) {
if (num_matrices <= block_dim) {
run_tri_inv_rec_unroll<InputT, OutputT, 1 /* NumTilesPerCubeIter */, false /* IsBSND */>(
tensor_out, tensor_in, minus_eye_in, block_dim, matrix_size, num_matrices, num_bsnd_heads, is_lower,
cu_seqlens
);
} else if (num_matrices <= 2 * block_dim) {
run_tri_inv_rec_unroll<InputT, OutputT, 2 /* NumTilesPerCubeIter */, false /* IsBSND */>(
tensor_out, tensor_in, minus_eye_in, block_dim, matrix_size, num_matrices, num_bsnd_heads, is_lower,
cu_seqlens
);
} else {
run_tri_inv_rec_unroll<InputT, OutputT, 4 /* NumTilesPerCubeIter */, false /* IsBSND */>(
tensor_out, tensor_in, minus_eye_in, block_dim, matrix_size, num_matrices, num_bsnd_heads, is_lower,
cu_seqlens
);
}
} else {
if (num_matrices <= block_dim) {
run_tri_inv_rec_unroll<InputT, OutputT, 1 /* NumTilesPerCubeIter */, true /* IsBSND */>(
tensor_out, tensor_in, minus_eye_in, block_dim, matrix_size, num_matrices, num_bsnd_heads, is_lower,
cu_seqlens
);
} else if (num_matrices <= 2 * block_dim) {
run_tri_inv_rec_unroll<InputT, OutputT, 2 /* NumTilesPerCubeIter */, true /* IsBSND */>(
tensor_out, tensor_in, minus_eye_in, block_dim, matrix_size, num_matrices, num_bsnd_heads, is_lower,
cu_seqlens
);
} else {
run_tri_inv_rec_unroll<InputT, OutputT, 4 /* NumTilesPerCubeIter */, true /* IsBSND */>(
tensor_out, tensor_in, minus_eye_in, block_dim, matrix_size, num_matrices, num_bsnd_heads, is_lower,
cu_seqlens
);
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -nP --type=cpp -C2 '\brun_tri_inv_rec_unroll_per_num_matrices\s*<'

Repository: hw-native-sys/simpler

Length of output: 898


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/kernels/aic/kernel_tri_inv_rec_unroll.cpp"

echo "== References to template params in this file =="
rg -n --fixed-strings "NumTilesPerCubeIter" "$FILE" || true
rg -n --fixed-strings "IsBSND" "$FILE" || true

echo "== All call sites using explicit template arguments =="
rg -nP --type=cpp '\brun_tri_inv_rec_unroll_per_num_matrices\s*<' "$FILE" || true

Repository: hw-native-sys/simpler

Length of output: 5231


Remove unused template parameters from run_tri_inv_rec_unroll_per_num_matrices

NumTilesPerCubeIter and IsBSND are not used for any compile-time branching inside run_tri_inv_rec_unroll_per_num_matrices—the body always forwards hardcoded 1/2/4 and false/true selected by runtime num_matrices / num_bsnd_heads, so the <half, half, 1, false> template arguments at the only call site are ignored and misleading.

♻️ Proposed signature + call-site cleanup
-template <typename InputT, typename OutputT, uint32_t NumTilesPerCubeIter, bool IsBSND>
+template <typename InputT, typename OutputT>
 AICORE void run_tri_inv_rec_unroll_per_num_matrices(
-    run_tri_inv_rec_unroll_per_num_matrices<half, half, 1, false>(
+    run_tri_inv_rec_unroll_per_num_matrices<half, half>(
         M_inv, M, I_neg, block_dim, matrix_size, num_matrices, 0, is_lower, nullptr
     );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/kernels/aic/kernel_tri_inv_rec_unroll.cpp`
around lines 789 - 830, The wrapper run_tri_inv_rec_unroll_per_num_matrices
currently has unused template parameters NumTilesPerCubeIter and IsBSND; remove
them from its template parameter list so it becomes template<typename InputT,
typename OutputT> AICORE void run_tri_inv_rec_unroll_per_num_matrices(...),
leaving the internal forwards to run_tri_inv_rec_unroll(...) unchanged (those
calls still specify NumTilesPerCubeIter and IsBSND as before). Update any call
sites that instantiate run_tri_inv_rec_unroll_per_num_matrices (e.g., places
that passed <half, half, 1, false>) to drop the unused template arguments so the
wrapper is instantiated only with InputT and OutputT. Ensure symbols to edit:
run_tri_inv_rec_unroll_per_num_matrices and its callers; do not change
run_tri_inv_rec_unroll signature.

* tensor(0) = M (INPUT) fp16 triangular matrices [num_matrices * N * N]
* tensor(1) = I_neg (INPUT) fp16 negative identity [N * N]
* tensor(2) = M_inv (OUTPUT) fp16 result [num_matrices * N * N]
* tensor(4) = config (INPUT) int64[4]: [matrix_size, num_matrices, is_lower, block_dim]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Wrong tensor index in arg-layout doc. The config is the 4th argument, read via orch_args.tensor(3) (Lines 47, 49), but the comment labels it tensor(4) and skips tensor(3).

📝 Proposed doc fix
- *   tensor(4) = config (INPUT)  int64[4]: [matrix_size, num_matrices, is_lower, block_dim]
+ *   tensor(3) = config (INPUT)  int64[4]: [matrix_size, num_matrices, is_lower, block_dim]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* tensor(4) = config (INPUT) int64[4]: [matrix_size, num_matrices, is_lower, block_dim]
* tensor(3) = config (INPUT) int64[4]: [matrix_size, num_matrices, is_lower, block_dim]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@examples/a2a3/tensormap_and_ringbuffer/triangular_inverse_example/kernels/orchestration/triangular_inverse_orch.cpp`
at line 20, The argument-layout comment is using the wrong tensor index: the
config is read via orch_args.tensor(3) in this file (see uses of
orch_args.tensor(3) around the config handling), but the doc comment currently
labels it as tensor(4) and omits tensor(3); update the comment so the config
line reads "tensor(3) = config (INPUT) int64[4]: [matrix_size, num_matrices,
is_lower, block_dim]" (and ensure other tensor indices in that comment are
sequential and accurate to the orch_args.tensor(N) usages).

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