Mixed CPU and GPU computations
If GPU memory is a limiting factor for your computation, it may be preferable to carry out particle operations on the CPU while the rest of the solver runs on the GPU. This involves four steps.
1. Set the JustPIC backend to the CPU
At the top of the script, set the JustPIC backend to the CPU; other packages may still run their own GPU work:
using JustPIC
const backend = JustPIC.CPU2. Allocate the mirrored arrays
At the memory-allocation stage, allocate GPU copies of the particle-derived CPU fields. For example, phase ratios on mesh vertices:
using CUDA
phv_GPU = cell_array(CUDA.CUDABackend, 0.0, (N_phases,), (nx + 1, ny + 1, nz + 1))where N_phases is the number of material phases and cell_array(CUDA.CUDABackend, ...) allocates a GPU-backed CellArray.
Similarly, allocate CPU copies of the GPU velocity field:
V_CPU = (
x = zeros(nx + 1, ny + 2, nz + 2),
y = zeros(nx + 2, ny + 1, nz + 2),
z = zeros(nx + 2, ny + 2, nz + 1),
)3. Copy particle-derived fields to the GPU
At each time step, transfer the particle-derived information from CPU to GPU memory. For example, the vertex phase proportions:
phv_GPU.data .= CuArray(phase_ratios.vertex).data4. Copy the velocity field to the CPU
At each time step, once the velocity computation on the GPU is finished, transfer the velocity to the CPU:
V_CPU.x .= TA(backend)(V.x)
V_CPU.y .= TA(backend)(V.y)
V_CPU.z .= TA(backend)(V.z)Because backend == JustPIC.CPU, TA(backend) converts the velocity fields to plain CPU arrays. Advection then uses the usual JustPIC API:
advection!(particles, RungeKutta2(), values(V_CPU), Δt)