CPU 最佳实践

本章重点介绍环境设置的最佳实践,以在CPU上进行训练和推理时获得最佳性能。

英特尔

超线程技术

对于特定的工作负载,如GNN领域,建议的默认设置以获得最佳性能是关闭超线程。关闭超线程功能可以在BIOS [1] 或操作系统级别 [2] [3] 完成。

替代内存分配器

替代的内存分配器,如tcmalloc,可能通过更高效的内存使用提供显著的性能改进,减少不必要的内存分配或释放的开销。tcmalloc使用线程本地缓存来减少线程同步的开销,通过使用自旋锁和每个线程的竞技场分别减少锁争用,并按大小分类内存分配以减少内存碎片化的开销。

为了利用tcmalloc提供的优化,请在您的系统上安装它(在Ubuntu上,tcmalloc包含在libgoogle-perftools4包中),并将共享库添加到LD_PRELOAD环境变量中:

export LD_PRELOAD=/lib/x86_64-linux-gnu/libtcmalloc.so.4:$LD_PRELOAD

OpenMP 设置

由于OpenMP是默认的并行后端,我们可以通过dgl.utils.set_num_threads()来控制性能,包括采样和训练。

如果未设置OpenMP线程数且数据加载器中的num_workers设置为0,OpenMP运行时通常会默认使用可用的CPU核心数。这在大多数情况下效果良好,也是DGL中的默认行为。

如果数据加载器中的num_workers设置为大于0,每个工作进程的OpenMP线程数将被设置为1。这是PyTorch中的默认行为。在这种情况下,我们可以将OpenMP线程数设置为主进程中的CPU核心数。

性能调优高度依赖于工作负载和硬件配置。我们建议用户尝试不同的设置,并选择最适合自己情况的设置。

数据加载器 CPU 亲和性

注意

此功能仅适用于dgl.dataloading.DataLoader。目前尚不适用于dgl.graphbolt中的dataloaders。

如果数据加载器的工作线程数大于0,请考虑使用DGL数据加载器类的use_cpu_affinity()方法,这通常会显著提高训练性能。

use_cpu_affinity 将设置适当的 OpenMP 线程数(等于为主进程分配的 CPU 核心数), 将数据加载器工作线程绑定到单独的 CPU 核心,并将主进程限制在剩余的 CPU 核心上。

在多NUMA节点设置中,use_cpu_affinity默认只会使用NUMA节点0的核心,假设工作负载在多个NUMA节点之间扩展效果不佳。如果您认为您的工作负载在利用多个NUMA节点时会有更好的性能,您可以传递用于数据加载(loader_cores)和计算(compute_cores)的核心列表。

loader_cores 和 compute_cores 参数(CPU核心列表)可以传递给 enable_cpu_affinity,以便更好地控制应使用哪些核心,例如在工作负载在多个NUMA节点上扩展良好的情况下。

Usage:
dataloader = dgl.dataloading.DataLoader(...)
...
with dataloader.enable_cpu_affinity():
    <training loop or inferencing>

手动控制

有关OpenMP设置的高级和更细粒度控制,请参阅[4]文章《在CPU上最大化Intel® PyTorch*优化性能》

脚注

Total running time of the script: (0 minutes 0.000 seconds)

Gallery generated by Sphinx-Gallery