Some quick conclusions:
- there is only so much that the code can scale (at least in MPP+SMP mode)
- there is a "peak performance" point somewhere between 112 and 168 cores after which it doesn't make anymore sense to add any more computational power since it negatively affects the performance
- best performance can be achieved if nodes are undersubscribed
- up to 4 cores used per node can give very close to linear performance. Let's look at parallel efficiency values:
cpu_cores: 1 E = 99%
cpu_cores: 7 E = 99%
cpu_cores: 14 E = 97%
cpu_cores: 28 E = 94%
cpu_cores: 56 E = 81%
cpu_cores: 112 E = 68%
cpu_cores: 168 E = 37%
I will have to verify the last point in the next experiment where I run the code on 1-60 processors, subscribing only up to 4 CPUs per node. In the current experiment 28 cores (4 per node) provide 94% efficiency which sounds fairly good to me.
Next, parallel timings:
It is clear from the graph that starting from 4 cores per node processes start under-performing and create visible load imbalance. There is no actual load imbalance: all nodes have exactly the same amount of work to do, but probably due memory accessing bottlenecks some processors wait longer to get their data from memory while others have to wait in the collective routing for the former to complete their computations. In addition to that, the increasing time spent in the MPI_Gather collective is definitely not representing the real communication overheads: if it was then the broadcasting time would be increasing as well because the amount of data broadcast by node 0 on each iteration is greater than the amount of data it has to gather by the corresponding collective routine. The only explanation for why broadcasting time is very small is that it happens after another collective - MPI_Gather, which implicitly synchronises all nodes, and the actual communication time for this routine is very small.















