14 Affinity: Truce with the kernel

 

This chapter covers

  • Why affinity is an important concern for modern CPUs
  • Controlling affinity for your parallel applications
  • Fine-tuning performance with process placement

We first encountered affinity in section 8.6.2 on the MPI (Message Passing Interface), where we defined it and briefly showed how to handle it. We repeat the definition here and also define process placement.

  • Affinity—Assigns a preference for the scheduling of a process, rank or thread to a particular hardware component. This is also called pinning or binding.
  • Placement—Assigns a process or thread to a hardware location.

We’ll go into more depth about affinity, placement, and the order of threads or ranks in this chapter. Concerns about affinity are recent phenomena. In the past, with just a few processor cores per CPU, there wasn’t that much to gain. As the number of processors grows and the architecture of a compute node gets more complicated, affinity has become more and more important. Still, the gains are relatively modest; perhaps the biggest benefit is in reducing the variation in performance from run to run and getting better on-node scaling. Occasionally, controlling affinity can avoid truly disastrous scheduling decisions by the kernel with respect to the characteristics of your application.

14.1 Why is affinity important?

14.2 Discovering your architecture

14.3 Thread affinity with OpenMP

14.4 Process affinity with MPI

14.4.1 Default process placement with OpenMPI

14.4.2 Taking control: Basic techniques for specifying process placement in OpenMPI

14.4.3 Affinity is more than just process binding: The full picture

14.5 Affinity for MPI plus OpenMP

14.6 Controlling affinity from the command line

14.6.1 Using hwloc-bind to assign affinity

14.6.2 Using likwid-pin: An affinity tool in the likwid tool suite

14.7 The future: Setting and changing affinity at run time

14.7.1 Setting affinities in your executable

14.7.2 Changing your process affinities during run time

14.8 Further explorations