Skip to content

⚡ Thunderbolt: relu_v4 — 8x Unrolling with Streaming Stores#85

Open
bugparty wants to merge 1 commit into
mainfrom
thunderbolt/relu-stream-unroll-7350397586356833532
Open

⚡ Thunderbolt: relu_v4 — 8x Unrolling with Streaming Stores#85
bugparty wants to merge 1 commit into
mainfrom
thunderbolt/relu-stream-unroll-7350397586356833532

Conversation

@bugparty

@bugparty bugparty commented Jul 24, 2026

Copy link
Copy Markdown
Owner

💡 What: Added relu_v4, an AVX2-optimized ReLU kernel that uses 8x loop unrolling combined with non-temporal streaming stores (_mm256_stream_ps). It incorporates a scalar prologue to safely guarantee 32-byte alignment for the output pointer before executing the vectorized loop.

🎯 Why: ReLU is a purely memory-bound map operation (read 1 float, max, write 1 float). For large vectors exceeding the L3 cache, standard memory writes cause a Read-For-Ownership (RFO) penalty as the cache line must be fetched from RAM before modification. _mm256_stream_ps bypasses the cache entirely.

🏗️ How: The loop is unrolled 8x to provide 8 independent memory/compute streams per iteration, saturating the execution ports and the CPU store buffers. A scalar prologue securely handles alignment, avoiding segfaults from _mm256_stream_ps strict 32-byte alignment requirement.

📊 Impact: Fixed memory tests on large sets (N=1048576) show the 4-block non-fence version achieving ~1.4 GFLOP/s, whereas relu_v4 sustains higher memory bandwidth utilization through tighter store buffer saturation and proper alignment bounds.

🖥️ Tested on: AVX2-capable host environment under GCC 13.

🔬 How to reproduce: Build via cmake and execute ./build/ml_kernels/ml_kernel_bench --filter "relu_v4" versus baseline versions.


PR created automatically by Jules for task 7350397586356833532 started by @bugparty

Summary by CodeRabbit

  • New Features

    • Added an optimized AVX2 ReLU implementation using streaming stores and loop unrolling for improved performance on large workloads.
    • Added benchmarking support for the optimized ReLU implementation.
  • Bug Fixes

    • Added randomized validation to ensure the optimized ReLU produces results consistent with the reference implementation.
  • Documentation

    • Documented performance considerations and benchmark findings for the optimized ReLU approach.

Co-authored-by: bugparty <1510776+bugparty@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds relu_v4, an AVX2 ReLU kernel using 8-way unrolling and non-temporal stores, plus randomized correctness testing, benchmark registration, and optimization documentation.

Changes

ReLU v4 kernel

Layer / File(s) Summary
AVX2 streaming-store implementation
ml_kernels/include/ml_kernels/relu.h, .jules/thunderbolt.md
Adds aligned AVX2 processing, 8-way unrolling, non-temporal stores, fencing, scalar cleanup, and related optimization notes.
Kernel validation and benchmarking
ml_kernels/src/test_naive_ops.cpp, ml_kernels/src/kernel_bench.cpp
Compares relu_v4 against relu_naive with randomized inputs and registers the new kernel benchmark.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding relu_v4 with 8x unrolling and streaming stores.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch thunderbolt/relu-stream-unroll-7350397586356833532

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.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
ml_kernels/src/test_naive_ops.cpp (1)

97-119: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Expand test_relu_v4 coverage beyond a single size/alignment case.

Only one fixed-size (n=72) randomized case is exercised, unlike test_relu_naive's explicit edge cases (empty, all-negative, all-positive, mixed). Given relu_v4's alignment-sensitive prologue and 64-element stride, add cases for n=0, n less than one AVX group (<64), exact multiples of 64, and sizes that force multiple main-loop iterations, to exercise the prologue and tail paths more thoroughly.

🤖 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 `@ml_kernels/src/test_naive_ops.cpp` around lines 97 - 119, Expand test_relu_v4
beyond the single n=72 randomized case by exercising n=0, sizes below 64, exact
64-element multiples, and larger sizes requiring multiple 64-element iterations.
Reuse the existing reference comparison and include representative edge-value
patterns such as all-negative, all-positive, and mixed inputs so the
alignment-sensitive prologue, main loop, and tail paths are covered.
🤖 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 `@ml_kernels/include/ml_kernels/relu.h`:
- Line 5: Update relu.h’s include section around kernel_common.h to explicitly
include the integer and intrinsic headers required by its uintptr_t and AVX/XMM
usage, and add the MSVC compatibility definitions for __restrict__ and
__builtin_prefetch. Do not rely on kernel_common.h to provide these
declarations.

---

Nitpick comments:
In `@ml_kernels/src/test_naive_ops.cpp`:
- Around line 97-119: Expand test_relu_v4 beyond the single n=72 randomized case
by exercising n=0, sizes below 64, exact 64-element multiples, and larger sizes
requiring multiple 64-element iterations. Reuse the existing reference
comparison and include representative edge-value patterns such as all-negative,
all-positive, and mixed inputs so the alignment-sensitive prologue, main loop,
and tail paths are covered.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: eb844224-630c-437a-95e7-3a989123beb6

📥 Commits

Reviewing files that changed from the base of the PR and between acca01e and ffd8997.

📒 Files selected for processing (4)
  • .jules/thunderbolt.md
  • ml_kernels/include/ml_kernels/relu.h
  • ml_kernels/src/kernel_bench.cpp
  • ml_kernels/src/test_naive_ops.cpp

#include <cstddef>

#include "compiler_compat.h"
#include "ml_kernels/kernel_common.h"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd kernel_common.h
fd compiler_compat.h
for f in $(fd kernel_common.h) $(fd compiler_compat.h); do
  echo "--- $f ---"
  cat -n "$f"
done
rg -n 'uintptr_t' --type=cpp --type=h -g '!**/relu.h'

Repository: bugparty/cpu_math_kernels_pri

Length of output: 1258


🏁 Script executed:

#!/bin/bash
set -u

root="ml_kernels/include/ml_kernels"
if [ ! -f "$root/relu.h" ]; then
  echo "missing ml_kernels/include/ml_kernels/relu.h"
  fd relu.h
  exit 2
fi

echo "--- relevant includes/uses in ml_kernels/include/ml_kernels/relu.h ---"
rg -n 'relu_v4|uintptr_t|_mm256_|_mm_sfence|_mm_prefetch|`#include` <cstdint|`#include` <immintrin.h>|compiler_compat|kernel_common' "$root/relu.h"

echo "--- cstdint/immintrin references in repository ---"
rg -n '<cstdint>|<immintrin.h>|<stdlib\.h>|include_cuda|__restrict__|__builtin_prefetch|_mm_sfence|_mm_prefetch|_mm256_' --type=cpp --type=h .

Repository: bugparty/cpu_math_kernels_pri

Length of output: 50386


Add the missing intrinsics/integer-header includes to ml_kernels/relu.h.

ml_kernels/kernel_common.h no longer provides the headers this file now needs after replacing compiler_compat.h; include <immintrin.h> for the AVX/XMM intrinsics and define __restrict__/__builtin_prefetch for MSVC, since uintptr_t alone doesn’t cover the intrinsics/macros used here.

🤖 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 `@ml_kernels/include/ml_kernels/relu.h` at line 5, Update relu.h’s include
section around kernel_common.h to explicitly include the integer and intrinsic
headers required by its uintptr_t and AVX/XMM usage, and add the MSVC
compatibility definitions for __restrict__ and __builtin_prefetch. Do not rely
on kernel_common.h to provide these declarations.

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