Skip to content

Add atomicAdd for numerators, and remove denominators from kernel - #59

Merged
Qubitol merged 1 commit into
madnis-paperfrom
feat-numerators-atomicadd
Aug 7, 2026
Merged

Add atomicAdd for numerators, and remove denominators from kernel#59
Qubitol merged 1 commit into
madnis-paperfrom
feat-numerators-atomicadd

Conversation

@Qubitol

@Qubitol Qubitol commented Aug 6, 2026

Copy link
Copy Markdown
Member

Adding atomic add in the main kernel allow to sum over the helicity, reducing the dimensionality of the numerators array.

Denominators are calculated starting from numerators.

Results

Comparison of the implementations in feat-atomic-add (f8ce451) with main (5f2b574).

Hardware:

  • CPU: AMD EPYC 9654 96-Core Processor
  • GPU: NVIDIA H100 NVL (95,830 MiB)

Standalone tests

Every figure compares the two implementations at fixed process, block count, and 256 threads per block.

We tested only the following processes, obtained in standalone mode:

  • 2g: g g > t t~ g g
  • 3g: g g > t t~ g g g

The upper x-axis reports CUDA blocks.
The lower x-axis reports grid size, blocks × threads, which is the effective batch size in these tests.

Results availability

availability_2g availability_3g

Some tests failed more on the 3g side since it is more intensive on memory.

Validation: is the matrix element the same?

Yes, we obtain matrix element values equal digit by digit

mean_matrix_element_2g mean_matrix_element_3g

Comparison

Here we compare both the throughput of the matrix element as obtained from the check_sa.exe execution, and the peak memory, as obtained by nvidia-smi:

  • check_sa.exe perf <blocks> 246 10
  • nvidia-smi --query-gpu=memory.used --loop-ms=50 --format=csv --filename=<memory_gpu.csv>
throughput_and_memory_2g throughput_and_memory_3g

Conclusions

The addition of the atomic addition seemed to have improved both the throughput, and most importantly, the memory imprint on the GPU.

Gridpack tests

Every figure shows a gridpack run executed with MadNIS, and generating 1000000 events.
We varied the two parameters:

  • gpu_thread_pool_size
  • gpu_batch_size

We tested only the following processes, obtained in standalone mode:

  • p p > t t~ j j
  • p p > t t~ j j j

Summary and validation

Throughput gains are evaluated only where both implementations completed the same configuration.
Generation throughput is process.count_unweighted / run_times.generate.wall_time_sec.

The mean pull is

$$\frac{\mathrm{mean}_{\mathrm{atomic}}-\mathrm{mean}_{\mathrm{main}}}{\sqrt{\mathrm{error}_{\mathrm{atomic}}^2+\mathrm{error}_{\mathrm{main}}^2}}.$$

variant available highest-throughput batch highest-throughput threads generation throughput [events/s] generate wall [s] peak memory [GiB]
0 main · 5f2b574 7/20 64,000 2 45,412 22.02 55.6
1 atomicAdd · fb197f1 15/20 64,000 1 138,354 7.23 8.7
gpu_batch_size gpu_thread_pool_size generation throughput gain mean pull atomic/main efficiency
0 64,000 1 3.07× +0.58σ 1.90×
1 64,000 2 2.85× +1.22σ 1.68×
2 64,000 4 2.96× +0.34σ 1.69×
4 128,000 1 2.96× -0.40σ 1.93×
5 128,000 2 2.90× +0.21σ 1.87×
8 256,000 1 3.32× -3.29σ 2.04×
9 256,000 2 3.02× +1.10σ 1.73×
  • Common successful configurations: 7
  • atomicAdd generation-throughput gain: 2.85–3.32×
  • Largest absolute mean pull: 3.29σ

Physics validation can be also seen by this plot:

process_mean_validation

Results availability

availability

Some tests failed because they were going out of memory.

Peak memory comparison

peak_memory_grid

Runs marked with a red cross failed.

Unweighting efficiency comparison

The unweighting efficiency has been calculated by the ratio process.count_target / process.count_after_cuts_opt.

unweighting_efficiency

Throughput scaling

generation_throughput_scaling

Conclusions

  • This little change brought better speedup with less memory.
  • If everyone is ok with this and with the physics validation (there is a ≈3σ pull), then we can merge.

These changes will be merge with the branch that will be used for the tests of the paper.

Adding atomic add in the main kernel allow to sum over the helicity,
reducing the dimensionality of the numerators array.
Denominators are calculated starting from numerators.

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

amazing job !! first I thought that atomic add would actually cost, but probably the reduced memory is outweighing this? please have a look also at the comment in the code diff.

@Qubitol
Qubitol merged commit bbf3e1b into madnis-paper Aug 7, 2026
252 of 256 checks passed
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.

3 participants