Working with GPUs
POLFED spends most runtime in spectral transformation, i.e. repeated matrix-vector or matrix-matrix products inside polynomial filtering.
GPUs are often much faster for this workload because:
- mapping is massively data-parallel,
- POLFED kernels are largely memory-bound and GPUs provide much larger memory bandwidth,
- regular access patterns can be executed efficiently by many concurrent threads.
In practical usage the interface is almost unchanged: you move arrays to CUDA, then call polfed the same way as on CPU.
1) Running QSun on CPUs
using Polfed
using Polfed.Models: qsun_hamiltonian
using LinearAlgebra
L_loc = 12
L_grain = 2
g0 = 1.0
α = 0.5
mat_cpu = qsun_hamiltonian(L_loc, L_grain, g0, α; use_sparse=true)
x0_cpu = rand(size(mat_cpu, 1)); x0_cpu ./= norm(x0_cpu)
howmany = 80
target = 0.0
vals_cpu, vecs_cpu, report_cpu = polfed(
mat_cpu, x0_cpu, howmany, target; produce_report=true
)
display_report(report_cpu)2) Running QSun on GPUs
using CUDA
mat_gpu = CuArray(Matrix(mat_cpu))
x0_gpu = CUDA.rand(Float64, size(mat_gpu, 1))
x0_gpu ./= norm(x0_gpu)
vals_gpu, vecs_gpu, report_gpu = polfed(
mat_gpu, x0_gpu, howmany, target; produce_report=true
)
display_report(report_gpu)The call pattern is basically the same; the main difference is array type (Array vs CuArray). Comparing report_cpu and report_gpu with display_report usually shows large speedups.
In many workloads this speedup is "almost for free" at the software level: once GPU hardware is available, the code path change is small.
More detail on optimization patterns and speedup behavior is covered in the advanced tutorials.