← All Experiences

GPU Computing · CFD · Research

CUDA CFD Optimization

Profiled and reworked a lattice Boltzmann GPU solver to remove hidden compute and memory bottlenecks—then validated every speedup against the simulation's accuracy limits.

Mechanical Engineering Intern · Petrobras / Geoenergia Lab, UDESC · Jun–Aug 2025 · Santa Catarina, Brazil

Channel-flow CFD simulation post-processed in ParaView
Validated channel-flow output after the solver changes.
400%+MLUPs gain
+60%Warp efficiency
56 → 36 KBShared memory
+33%Peak Reynolds number

The lab's higher-order physics kernels were running roughly 10× slower than expected. The task was not simply to make code faster—it was to find the actual limiting hardware behavior and preserve valid CFD results.

System

D3Q19 lattice solver

Collision and streaming operations update independent lattice sites, making the method well suited to GPU parallelism.

Constraint

Accuracy had to hold

Precision and grid changes were checked against established simulation tolerances at every step.

My ownership

Profile → change → validate

I owned kernel profiling, targeted optimization, grid-generation tooling, and technical handoff to the lab.

D3Q19 lattice configuration used by the solver
D3Q19 lattice model.
CUDA grid block and thread hierarchy
CUDA execution hierarchy.
Curved boundary representation for the CFD solver
Boundary-method development.

Manual timers and refactoring did not explain the slowdown. Hardware-level profiling did: Nsight Compute exposed lingering double-precision FMA instructions in the hottest loops and Nsight Systems showed where runtime accumulated.

Trace

Locate expensive kernels and distinguish compute time from memory stalls.

Inspect

Use source-correlated metrics to identify FP64 instructions and access patterns.

Validate

Re-run benchmark cases and confirm the solution remains inside tolerance.

Timeline profiling in NVIDIA Nsight Systems
System-level timeline: where runtime accumulated.
Kernel source view in NVIDIA Nsight Compute
Kernel source view: the instruction-level evidence.
Precision

Validated FP64 → FP32

Removed unnecessary double-precision work from hot loops while checking error against simulation tolerances.

Memory

Coalesced data access

Restructured thread-to-data mapping to reduce long scoreboard stalls and improve warp efficiency by 60%.

Occupancy

Reused shared data

Cut peak shared-memory use from 56 KB to 36 KB, allowing more active work on the same hardware.

400%+ MLUPs gain

The precision and kernel changes produced the largest throughput improvement, with higher-order kernels improving by roughly 500% while remaining inside the lab's validation limits.

Boundary instability required a geometry change, not another low-level optimization. I generated multiresolution interfaces with a fine lattice near boundaries and a coarser interior.

Fine boundary lattice in red surrounding a coarse interior lattice
Python-generated fine/coarse interface geometry.
Outcome

Higher stable flow regime

The grid tool increased peak simulated Reynolds number by 33% without reducing throughput. I also delivered ParaView scripts, an Nsight manual, and a training video so the lab could repeat the workflow.

CUDAC++PythonNsight ComputeNsight SystemsLBM / CFDParaView