More efficient mpi sorting - #415
Conversation
…_sort to when actually needed
|
Fixed the merge conflicts in 71ab6c4 A question is whether we put |
Yes, I think this is a good idea. If I understand it right, the benifit woud be that in both the |
Addresses also #402
The basic new things are two new keywords
pushes_etaandlocal_eval_onlyfor pyccel kernels; they reduce the calls to mpi_sort to when actually needed.I now see a good strong scaling for usual VlasovAmpere and ColdPlasmaVlasov test cases.
Opus 5.5:
I've implemented the plan and it cuts
mpi_sort_markerscalls by 2× to 10× depending on the model, with no change in results.What changed
pusher.py
pushes_eta: boolis a new required keyword, so a newPusher(...)call can't forget it.False, the pusher never sorts, and passing ampi_sortvalue raises an assert.True, the markers are always sorted at the end:mpi_sort=Nonebecomes"last".local_eval_only: bool = False: when True, sorting happens only after the last stage. It asserts there are noeval_kernels._sort_for_alpha(). It tracks the alpha the markers were last sorted for in_sorted_for.put_particles_in_boxesstill runs per stage, as you asked. Markers outside the local domain get the overflow box index, so this is safe withlocal_eval_only.Call sites (all 17)
local_eval_only=True(pluspushes_eta=True):PushEtaandPushRandomDiffusion. I dropped their explicitmpi_sort="each".pushes_eta=True:PushEtaPC,PushDeterministicDiffusion, and both guiding-center propagators (implicit and explicit).pushes_eta=False: the 9 velocity/weight pushers. I checked that none of their kernels writemarkers[ip, 0:3]._bench_push_vxb_analytic.py.Sort calls over 3 time steps (default params, same count on 2 and 4 ranks)
Checks
test_pushers.py: 102 passed on 1, 2 and 4 ranks.ruff formatandruff checkare clean.git stash) against new code on 1, 2 and 4 ranks with a fixed seed and compared the final markers by ID:A separate bug I found while checking (not fixed)
With
pseudo_randomloading under MPI, marker IDs are duplicated at rank boundaries: 14 to 54 duplicates for Np=5000._first_marker_id(base.py:1167) is computed from the estimatedn_mks_load, but loading then resets it to the actual counts, so neighbouring ranks' ID ranges overlap. The defaultLoadingParameters()also hasseed=None, so each rank draws a different random stream. This made the first old-vs-new comparison look badly broken until I excluded the duplicate IDs. The fix should be about one line; I can do it separately if you want.Not done yet
current_coupling_5d_gradb.py.PushEtaPCor the diffusion propagators directly.I also saved two memory notes: one on the new
pushes_eta/local_eval_onlyrules, one on the duplicate-ID issue.