Running GROMACS on GPU instances
Comparing the performance of real applications across different Amazon Elastic Compute Cloud (Amazon EC2) instance types is the best way we’ve found for finding optimal configurations for HPC applications here at AWS.
Previously, we wrote about price-performance optimizations for GROMACS that showed how the GROMACS molecular dynamics simulation runs on single instances, and how it scales across many instances. In that post, we covered a variety of CPU-only Amazon EC2 instances. In this three-part series of posts, we will be extending that analysis to include instances with GPUs. Similar to last time, we’ll also consider instances with and without Elastic Fabric Adapter (EFA), our high performance network capabilities.
Specifically, the first part will cover some background on GROMACS and how it utilizes GPUs for acceleration; the second part will cover the price performance of GROMACS on GPU instance families running on a single instance; and the third part will cover the price performance of GROMACS running across multiple GPU instances, with and without EFA.
Part 1: How GROMACS utilizes GPUs for acceleration
GROMACS is a molecular dynamics (MD) package designed for simulations of solvated proteins, lipids, and nucleic acids. It is open-source and released under the GNU Lesser General Public License (LGPL). GROMACS runs on CPU and GPU nodes in single-node and multi-node (cluster) configurations. See https://www.gromacs.org/ for more information.
Before we talk about the runs and results, it’s worth briefly diving into what happens in an MD simulation and how GROMACS approaches the challenges associated with it. This will help us to choose optimal hardware for fast and efficient MD simulations.
In Molecular Dynamics, Newton’s equations of motion are integrated for a system of N particles, which could be the atoms of a protein in solution, for instance. The interactions between the particles are described by a potential that is called the force field. It includes bonded interactions that model the chemical bonds, as well as non-bonded, electrostatic (Coulomb) and van der Waals interactions that act between all atoms. From the positions of the atoms and the potential, the interatomic forces are calculated, which are then used to update the velocities and the positions of the atoms. This is done in a loop over many millions of time steps until a desired time span of the dynamics of the system is captured in the form of a trajectory that contains the positions as a function of time.
GROMACS tries to make use of all the hardware (CPUs, GPUs) available on a compute node to maximize the simulation performance. In contrast to scientific codes that run exclusively on CPUs or natively on GPUs, GROMACS uses an offloading approach. That means, the main loop over the time steps that update the position of the particles is run on the CPU, while portions of the interactions are offloaded to the GPU to be efficiently computed there. Since GROMACS version 4.6, the non-bonded interactions, which account for the main part of the calculations needed in an MD step, can be offloaded to GPUs.
A big advantage of this approach is that only the offloaded interactions need a GPU implementation (i.e. require CUDA or OpenCL code), while the main code base with its numerous algorithms that already exist in C++ does not need to be ported to the GPU. Later on, when new functionality is introduced, we still get increased simulation performance from the GPUs even though the new functionality is implemented solely on the CPU.
Another advantage of offloading is that both CPU and GPU FLOPS — floating point operations per second — are put to good use. This leads to very good performance on nodes that have both a powerful CPU and GPU installed. Ideally, CPU and GPU finish their computations at about the same time in the time step, so that no cycles are lost waiting. Luckily, as a result of the Particle Mesh Ewald algorithm used to calculate electrostatic interactions, the computational intensity between the short-range part (calculated on the GPU, if present) and the long-range part (calculated on the CPU) of these interactions can be adjusted. GROMACS does this automatically at the start of each run to balance computations between GPU and CPU to minimize idle times during the time step.
However, the offloading approach requires us to have at least some balance of CPU to GPU capacity. Having only CPUs will work, because all algorithms can run on the CPU, but it doesn’t work the other way around (yet). If we have too little CPU FLOPS for too much GPU FLOPS, GROMACS will try to compensate by shifting as many interactions as possible to the GPU. But with too little CPU compute capacity, the GPU will starve, waiting for the CPU to catch up, and effectively leaving GPU FLOPS unused and leaving performance gains on the table.
GROMACS’ multi-level parallelism
GROMACS makes use of parallelism on multiple levels:
- Domain Decomposition with dynamic load balancing: To distribute an MD system across multiple processors or nodes, GROMACS uses 3D domain decomposition. This means the simulation box containing the atoms is sliced into nx x ny x nz domains and each domain is assigned to an MPI rank, as shown in the Figure 1 for the example of 72 ranks. The MPI ranks can be distributed across multiple nodes. To account for any possible non-homogeneity in the system that would lead to an unequal amount of computation between the domains, a dynamic load balancing (DLB) mechanism is in place that adjusts the domain sizes throughout the simulation.
- Thread parallelism: The interactions that have to be calculated for the atoms of a domain can be operated on by multiple threads or cores via OpenMP parallelism. Thus, each MPI rank can have several OpenMP threads: usually between 2 and 10 for optimal performance.
- SIMD parallelism: For each thread, the SIMD (single instruction multiple data) units of the CPU cores are exploited with specially designed kernels for the different interaction types. One mechanism for optimal simulation performance is to select at compile time the most advanced SIMD instruction set supported by the CPU. If GROMACS is run on the same machine as it was compiled on, the correct SIMD level is automatically picked up during the CMake configuration step. When cross-compiling it needs to be set explicitly.
- GPU offloading: Additionally, the different types of interactions that have to be calculated for a domain (where a domain is equal to an MPI rank) can be offloaded to a GPU, if one’s available. If there are fewer GPUs than ranks, multiple ranks can offload to the same GPU. Depending on how exactly the input file is defined (e.g. which algorithms it uses) some or all types of interactions might be offloaded. For very fast GPUs (relative to the CPU) the simulation performance benefits from offloading as many interactions as possible to the GPU. For balanced CPU:GPU capacity, we want to offload only a portion of the interactions.
In practice, with GPUs, we usually offload the short-range part of the nonbonded interactions (i.e. the electrostatic and van der Waals interactions) to a GPU, while the long range part of the electrostatic interactions stays with the CPUs. The PME algorithm we mentioned before (which very efficiently computes the electrostatic interactions in most MD packages) allows us to balance the computational work between the short range and the long range part of the electrostatic interactions so that it can adapt to really quite diverse CPU:GPU compute ratios.
With fast GPUs we can offload more of the long-range part of the electrostatic interactions to get better performance. But while the long-range part of electrostatics can be parallelized over multiple CPUs, at the moment it can’t use multiple GPUs … yet.
In this first-of-three blog post, we covered the necessary background of what GROMACS does and how it utilizes CPU and GPU resources. In part 2 of this series, we will cover the price-performance characteristics for GROMACS running on single EC2 instances.