Skip to content

⚡ Thunderbolt: Softmax — 8x Unrolling Optimization#83

Open
bugparty wants to merge 1 commit into
mainfrom
thunderbolt-softmax-8x-unroll-1136076901946106662
Open

⚡ Thunderbolt: Softmax — 8x Unrolling Optimization#83
bugparty wants to merge 1 commit into
mainfrom
thunderbolt-softmax-8x-unroll-1136076901946106662

Conversation

@bugparty

@bugparty bugparty commented Jul 20, 2026

Copy link
Copy Markdown
Owner

💡 What: Aggressive 8x unrolling across all map-reduce phases of the AVX2 softmax kernel (softmax_v6), processing 64 elements per iteration.

🎯 Why: Complex mathematical sequences like the _mm256_max_ps and multi-instruction exp256 approximations exhibit FMA latencies that can bottleneck 4x unrolled implementations. 8x unrolling effectively hides this latency by maintaining 8 independent accumulator chains without causing YMM register spilling.

🏗️ How: 8x unrolling across the max, exp/sum, and normalization loops explicitly utilizing 8 unique YMM registers per section while keeping standard scalar fallbacks for the remainder.

📊 Impact: Showed up to ~5.56 GFLOP/s vs ~5.19 GFLOP/s (softmax_v5) on N=16384 arrays in fixed-memory benchmarking, confirming transition toward a throughput-bound behavior.

🖥️ Tested on: Intel(R) Xeon(R) Processor @ 2.30GHz, Linux, GCC 13.3.0.

🔬 How to reproduce:

  1. cd build && make -j$(nproc)
  2. ./ml_kernels/ml_kernel_bench --filter "softmax_v6"

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

Summary by CodeRabbit

  • New Features

    • Added the softmax_v6 AVX2 softmax implementation with enhanced parallel processing for improved throughput on large inputs.
    • Added benchmark coverage for comparing softmax_v6 performance.
  • Bug Fixes

    • Added correctness validation to ensure accurate outputs and normalized results across larger input sizes.
  • Documentation

    • Documented performance guidance favoring 8-way unrolling when system resources allow.

Adds aggressive 8x unrolling to hide max and exp calculation latencies.

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 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds the AVX2 softmax_v6 kernel with 8-way unrolling across reduction, exponentiation, summation, and normalization phases, then registers it for benchmarking and adds correctness tests for larger inputs.

Changes

Softmax v6

Layer / File(s) Summary
Implement 8-way unrolled softmax
ml_kernels/include/ml_kernels/softmax.h, .jules/thunderbolt.md
Adds softmax_v6 with 64-element SIMD blocks, unrolled reductions and normalization, scalar tail handling, and related optimization notes.
Register and validate the kernel
ml_kernels/src/kernel_bench.cpp, ml_kernels/src/test_naive_ops.cpp
Registers the softmax_v6 benchmark and compares its 72-element output with softmax_naive, including sum validation.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

🚥 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 and concisely summarizes the main change: an AVX2 softmax optimization using 8x unrolling.
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-softmax-8x-unroll-1136076901946106662

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.

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

184-214: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Test doesn't exercise softmax_v6's scalar tail path.

Input length is 72 (=64+8), so n % 8 == 0 and n % 64 == 8; the single-element scalar tail loops in softmax_v6 (max/sum/normalize) never execute for this test. Consider using a length not divisible by 8 (e.g. drop or add one element) to cover the scalar fallback path.

🤖 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 184 - 214, Update
test_softmax_v6 so its input length is not divisible by 8, ensuring softmax_v6
executes its scalar tail handling in the max, sum, and normalization passes.
Adjust the test data or add a single element while preserving the existing
naive-versus-v6 comparison and sum-to-one assertions.
🤖 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.

Nitpick comments:
In `@ml_kernels/src/test_naive_ops.cpp`:
- Around line 184-214: Update test_softmax_v6 so its input length is not
divisible by 8, ensuring softmax_v6 executes its scalar tail handling in the
max, sum, and normalization passes. Adjust the test data or add a single element
while preserving the existing naive-versus-v6 comparison and sum-to-one
assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 772ea217-f65d-4003-ae8d-cd11b814c483

📥 Commits

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

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

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