Skip to content

Some improvements to the CUDA C++ version - #27

Open
giordano wants to merge 4 commits into
UCL-ARC:masterfrom
giordano:patch-1
Open

Some improvements to the CUDA C++ version#27
giordano wants to merge 4 commits into
UCL-ARC:masterfrom
giordano:patch-1

Conversation

@giordano

Copy link
Copy Markdown
Member

Still work in progress, but this version I already get a decent speedup compared to the current version.

CC @qiUip who suggested all the algorithmic improvements.

Comment thread cuda_pi_dir/calculate_pi.cu Outdated
Comment thread cuda_pi_dir/calculate_pi.cu
This uses clearer variables names, and a large number of blocks
@giordano
giordano marked this pull request as ready for review February 13, 2026 17:56
@giordano

giordano commented Feb 13, 2026

Copy link
Copy Markdown
Member Author

So, I took inspiration from the paper GROMACS Unplugged: How Power Capping and Frequency Shapes Performance on GPUs where they used a Pi Solver

launched with 4096 blocks × 512 threads to fully utilize the computational resources of modern GPUs, including the NVIDIA A100, A40, L4, and L40.

Frustratingly they don't share the code of their solver, luckily we had a similar existing application, only had to tweak the launch parameters.

Some numbers on Cricket (Nvidia A100): C++ (compiled with NVCC 12.6, with nvcc -arch=sm_80 -o calculate_pi calculate_pi.cu), before PR:

$ ./calculate_pi 
Calculating PI using:
  1000000000 slices
  1000 CUDA threads
Obtained value for PI: 3.1415926535897891
Time taken: 0.54366599999999998 seconds

after:

$ ./calculate_pi 
Calculating PI using:
  1099511627776 slices
  512 CUDA threads
Obtained value for PI: 3.1415926535897869
Time taken: 3.1384690000000002 seconds

Note the 3 orders of magnitude of difference in the number of slices.

Similarly, for Julia (v1.12.5, with CUDA.jl v5.9.6), before:

$ julia --project pi_cuda.jl 
  Activating project at `~/repo/pi_examples/julia_cuda_pi_dir`
  Warming up...done. [19.527s]

Calculating PI using:
  1000000000 slices
  64 CUDA threads(s)
Obtained value of PI: 3.1415926515897707
Time taken: 3.561 seconds

after:

$ julia --project pi_cuda.jl 
  Activating project at `~/repo/pi_examples/julia_cuda_pi_dir`
  Warming up...done. [18.532s]

Calculating PI using:
  1099511627776 slices
  512 CUDA threads(s)
Obtained value of PI: 3.141592653589793
Time taken: 3.015 seconds

And to confirm this is fully compute-bound, here is a roofline model from Nsight Compute of the new Julia implementation:
image
The pichunk kernel has well over 90% of compute throughput (the second time it runs, after the warmup to force compilation):
image

I'm sure this can still be improved, but I'm happy with the current status, seems to be a solid improvement for both implementations.

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