← All projects

Science

CPU/GPU parallel computing

Curvature computed with OpenMP, CUDA and OpenCL, with compared benchmarks.

Done Sprint S28-S29 · 13 points
In short, no jargon for non-developersRead the summaryClose
What it is
The same computation on 3D objects, done several ways: on one processor core, on all of them, and on the graphics card, with the times compared.
What it is for
To speed up heavy computations, in simulation, imaging or artificial intelligence.
What it shows
Spreading a computation to make it up to six times faster, without changing its result.

Parallel computing developed during my PhD

Source code

How the pieces fit together

Diagram: Mesh → Two passes (read) ; Benchmarks → Two passes (times every version) ; Two passes → OpenMP (same functions) ; Two passes → OpenCL (as kernels) ; Two passes → CUDA (same passes). read times every version same functions as kernels same passes Benchmarks bench.json, on the page Mesh flat arrays, neighbours Two passes angles, then curvature OpenMP sequential and parallel OpenCL double precision CUDA double and single

Benchmarks

The same curvature, computed by each version on tori from 50,000 to 3.2 million triangles; median time, adjacency already built, copies to the graphics card included.

Measured on Intel(R) Core(TM) i5-10400F CPU @ 2.90GHz (6 OpenMP threads on 12 logical processors), graphics card NVIDIA GeForce GTX 1660, under WSL 2; median of 7 runs.

Time on 3,198,732 triangles (shorter is better)

Sequential C++ : 531 ms, ×1.0 Sequential C++ 531 ms, ×1.0 OpenMP, 6 threads : 178 ms, ×3.0 OpenMP, 6 threads 178 ms, ×3.0 OpenCL (processor, PoCL) : 332 ms, ×1.6 OpenCL (processor, PoCL) 332 ms, ×1.6 CUDA, double precision : 110 ms, ×4.8 CUDA, double precision 110 ms, ×4.8 CUDA, single precision : 85.5 ms, ×6.2 CUDA, single precision 85.5 ms, ×6.2
TrianglesSequential C++OpenMP, 6 threadsOpenCL (processor, PoCL)CUDA, double precisionCUDA, single precision
49,7286.95 ms ×1.02.60 ms ×2.77.54 ms ×0.94.13 ms ×1.73.18 ms ×2.2
199,36230.4 ms ×1.08.91 ms ×3.421.6 ms ×1.410.6 ms ×2.912.3 ms ×2.5
799,236112 ms ×1.032.2 ms ×3.560.9 ms ×1.832.4 ms ×3.423.9 ms ×4.7
3,198,732531 ms ×1.0178 ms ×3.0332 ms ×1.6110 ms ×4.885.5 ms ×6.2

On the graphics card, in double precision: 33.8 ms copying to the card, 30.5 ms computing, 11.9 ms back, and 33.7 ms on the processor (allocations). In single precision the computation alone drops to 1.94 ms: this consumer card has 32 times fewer double-precision units than single-precision ones. For a single curvature the copies are what costs: computing on the card pays off when the data stays there.

Single precision strays by at most 1.2e-6 on an angle defect: enough to show colours, not to check Gauss-Bonnet to the millionth.

Why OpenMP is not six times faster: the vertex pass reads a lot of memory for little computation, and the bandwidth of this machine under WSL tops out at 5 to 6 GB/s whatever the number of threads (measured); the face pass, for its part, runs 4.5 times faster on 6 cores. With 12 threads, the ones spinning while they wait on the logical cores slow the others down: one thread per physical core is faster here.

Tech stack

  • C++
  • OpenMP
  • CUDA
  • OpenCL

Who does what

C++
The sequential reference, identical bit for bit to the topology project's, and the code shared by the parallel versions.
OpenMP
Spreads both passes over every core, with the same result bit for bit whatever the number of threads.
CUDA
The same passes on the NVIDIA graphics card (GTX 1660), in double precision (within 1e-12) and in single precision (measured gap).
OpenCL
The same passes on any OpenCL device, processor (PoCL) or graphics card, in double precision.

Definition of Done

  • Code reviewed, diff by diff
  • Unit and integration tests green
  • Green CI on Linux, Windows and macOS when compiled
  • README, REVIEW.md and DECISIONS.md up to date
  • Texts in French and English
  • Demo deployed and tested on mobile