評價此頁

使用 run_cpu 指令碼最佳化 Intel® Xeon® 上的 CPU 效能#

創建於:2024 年 6 月 25 日 | 最後更新:2025 年 7 月 1 日 | 最後驗證:2024 年 11 月 5 日

在 Intel® Xeon® 可擴充套件處理器上執行 PyTorch 推理時,有幾種配置選項會影響效能。為了獲得最佳效能,我們提供了 torch.backends.xeon.run_cpu 指令碼,該指令碼可最佳化執行緒和記憶體管理配置。對於執行緒管理,該指令碼配置執行緒親和性和 Intel® OMP 庫的預載入。對於記憶體管理,它配置 NUMA 繫結並預載入最佳化的記憶體分配庫,例如 TCMalloc 和 JeMalloc。此外,該指令碼為單例項和多例項場景中的計算資源分配提供了可調引數,幫助使用者嘗試針對特定工作負載最佳化資源利用率的協調。

您將學到什麼#

  • 如何利用 numactltaskset、Intel® OpenMP 執行時庫以及 TCMallocJeMalloc 等最佳化記憶體分配器來提升效能。

  • 如何配置 CPU 資源和記憶體管理,以最大化 PyTorch 在 Intel® Xeon® 處理器上的推理效能。

最佳化介紹#

應用 NUMA 訪問控制#

在單個插槽中為使用者提供越來越多的 CPU 核心是有益的,因為這提供了更強的計算資源。然而,這也會導致記憶體訪問競爭,從而可能因繁忙的記憶體而導致程式停頓。為了解決這個問題,引入了非統一記憶體訪問 (NUMA)。與所有記憶體對所有核心都同等可訪問的統一記憶體訪問 (UMA) 不同,NUMA 將記憶體組織成多個組。一定數量的記憶體直接連線到一個插槽的整合記憶體控制器,成為該插槽的本地記憶體。本地記憶體訪問比遠端記憶體訪問快得多。

使用者可以在 Linux 上使用 lscpu 命令獲取 CPU 資訊,以瞭解機器上有多少個核心和插槽。此外,此命令還提供 NUMA 資訊,例如 CPU 核心的分佈。下面是在配備 Intel® Xeon® CPU Max 9480 的機器上執行 lscpu 的示例

$ lscpu
...
CPU(s):                  224
  On-line CPU(s) list:   0-223
Vendor ID:               GenuineIntel
  Model name:            Intel (R) Xeon (R) CPU Max 9480
    CPU family:          6
    Model:               143
    Thread(s) per core:  2
    Core(s) per socket:  56
    Socket(s):           2
...
NUMA:
  NUMA node(s):          2
  NUMA node0 CPU(s):     0-55,112-167
  NUMA node1 CPU(s):     56-111,168-223
...
  • 檢測到兩個插槽,每個插槽包含 56 個物理核心。啟用超執行緒後,每個核心可以處理 2 個執行緒,每個插槽有 56 個邏輯核心。因此,該機器共有 224 個 CPU 核心在服務。

  • 通常,物理核心的索引在邏輯核心之前。在此場景中,核心 0-55 是第一個 NUMA 節點上的物理核心,核心 56-111 是第二個 NUMA 節點上的物理核心。

  • 邏輯核心隨後索引:核心 112-167 對應於第一個 NUMA 節點上的邏輯核心,核心 168-223 對應於第二個 NUMA 節點上的邏輯核心。

通常,執行具有計算密集型工作負載的 PyTorch 程式應避免使用邏輯核心以獲得良好的效能。

Linux 提供了一個名為 numactl 的工具,它允許使用者控制程序或共享記憶體的 NUMA 策略。它以特定的 NUMA 排程或記憶體放置策略執行程序。如上所述,核心在一個插槽中共享快取記憶體,因此避免跨插槽計算是個好主意。從記憶體訪問的角度來看,將記憶體訪問繫結在本地比訪問遠端記憶體要快得多。numactl 命令應已安裝在最近的 Linux 發行版中。如果缺少,您可以手動安裝它,例如在 Ubuntu 上使用安裝命令

$ apt-get install numactl

在 CentOS 上,您可以執行以下命令

$ yum install numactl

Linux 中的 taskset 命令是另一個強大的實用程式,它允許您設定或檢索正在執行程序的 CPU 親和性。taskset 已預裝在大多數 Linux 發行版中,如果未安裝,在 Ubuntu 上可以使用以下命令進行安裝

$ apt-get install util-linux

在 CentOS 上,您可以執行以下命令

$ yum install util-linux

使用 Intel® OpenMP 執行時庫#

OpenMP 是多執行緒的一種實現,多執行緒是一種並行化方法,其中主執行緒(按順序執行的一系列指令)分叉指定數量的子執行緒,然後系統將任務分配給它們。然後執行緒併發執行,執行時環境將執行緒分配給不同的處理器。使用者可以透過一些環境變數設定來控制 OpenMP 的行為以適應其工作負載,這些設定由 OMP 庫讀取和執行。預設情況下,PyTorch 使用 GNU OpenMP 庫 (GNU libgomp) 進行平行計算。在 Intel® 平臺上,Intel® OpenMP 執行時庫 (libiomp) 提供 OpenMP API 規範支援。與 libgomp 相比,它通常能帶來更高的效能優勢。

可以使用以下命令之一安裝 Intel® OpenMP 執行時庫

$ pip install intel-openmp

$ conda install mkl

選擇最佳化的記憶體分配器#

從效能角度來看,記憶體分配器也起著重要作用。更有效的記憶體使用減少了不必要的記憶體分配或銷燬的開銷,從而提高了執行速度。根據實踐經驗,對於深度學習工作負載,TCMallocJeMalloc 透過儘可能多地重用記憶體,比預設的 malloc 操作能獲得更好的效能。

您可以透過在 Ubuntu 上執行以下命令來安裝 TCMalloc

$ apt-get install google-perftools

在 CentOS 上,可以透過執行以下命令進行安裝

$ yum install gperftools

在 conda 環境中,也可以透過執行以下命令進行安裝

$ conda install conda-forge::gperftools

在 Ubuntu 上,可以使用此命令安裝 JeMalloc

$ apt-get install libjemalloc2

在 CentOS 上,可以透過執行以下命令進行安裝

$ yum install jemalloc

在 conda 環境中,也可以透過執行以下命令進行安裝

$ conda install conda-forge::jemalloc

快速入門示例命令#

  1. 使用 1 個 CPU 核心上的 1 個執行緒執行單例項推理(僅使用核心 #0)

$ python -m torch.backends.xeon.run_cpu --ninstances 1 --ncores-per-instance 1 <program.py> [program_args]
  1. 在單個 CPU 節點(NUMA 插槽)上執行單例項推理

$ python -m torch.backends.xeon.run_cpu --node-id 0 <program.py> [program_args]
  1. 執行多例項推理,在 112 核 CPU 上,每個例項使用 14 核,共 8 個例項

$ python -m torch.backends.xeon.run_cpu --ninstances 8 --ncores-per-instance 14 <program.py> [program_args]
  1. 以吞吐量模式執行推理,其中每個 CPU 節點上的所有核心都構成一個例項

$ python -m torch.backends.xeon.run_cpu --throughput-mode <program.py> [program_args]

注意

這裡的“例項”一詞並非指雲實例。此指令碼作為一個單一程序執行,該程序呼叫由多個執行緒組成的多個“例項”。在此上下文中,“例項”是一種執行緒組。

使用 torch.backends.xeon.run_cpu#

可以使用以下命令顯示引數列表和使用指南

$ python -m torch.backends.xeon.run_cpu –h
usage: run_cpu.py [-h] [--multi-instance] [-m] [--no-python] [--enable-tcmalloc] [--enable-jemalloc] [--use-default-allocator] [--disable-iomp] [--ncores-per-instance] [--ninstances] [--skip-cross-node-cores] [--rank] [--latency-mode] [--throughput-mode] [--node-id] [--use-logical-core] [--disable-numactl] [--disable-taskset] [--core-list] [--log-path] [--log-file-prefix] <program> [program_args]

上述命令具有以下位置引數

knob

help

program

要啟動的程式/指令碼的完整路徑。

program_args

要啟動的程式/指令碼的輸入引數。

選項說明#

通用選項設定(knobs)包括以下內容

knob

type

預設值

help

-h, --help

顯示幫助訊息並退出。

-m, --module

將每個程序解釋為 Python 模組,以與“python -m”相同的行為執行。

--no-python

布林值

避免在程式前新增“python” - 直接執行。當指令碼不是 Python 指令碼時很有用。

--log-path

str

''

指定日誌檔案目錄。預設路徑為 '',表示停用檔案日誌記錄。

--log-file-prefix

str

“run”

日誌檔名中的字首。

用於應用或停用最佳化的 knobs 是

knob

type

預設值

help

--enable-tcmalloc

布林值

啟用 TCMalloc 記憶體分配器。

--enable-jemalloc

布林值

啟用 JeMalloc 記憶體分配器。

--use-default-allocator

布林值

使用預設記憶體分配器。不會使用 TCMallocJeMalloc

--disable-iomp

布林值

預設情況下,如果安裝了 Intel® OpenMP 庫,將使用它。設定此標誌將停用 Intel® OpenMP 的使用。

注意

記憶體分配器會影響效能。如果使用者未指定所需的記憶體分配器,run_cpu 指令碼將按 TCMalloc > JeMalloc > PyTorch 預設記憶體分配器的順序搜尋是否安裝了其中任何一個,並採用第一個匹配的。

用於控制例項數量和計算資源分配的 knobs 是

knob

type

預設值

help

--ninstances

int

0

例項數量。

--ncores-per-instance

int

0

每個例項使用的核心數。

--node-id

int

-1

多例項使用的節點 ID,預設使用所有節點。

--core-list

str

''

指定核心列表,格式為 'core_id, core_id, ....' 或核心範圍 'core_id-core_id'。預設使用所有核心。

--use-logical-core

布林值

預設只使用物理核心。指定此標誌可啟用邏輯核心的使用。

--skip-cross-node-cores

布林值

防止工作負載在跨 NUMA 節點的上執行。

--rank

int

-1

指定例項索引以分配 ncores_per_instance;否則 ncores_per_instance 將按順序分配給例項。

--multi-instance

布林值

在多插槽 CPU 伺服器上呼叫工作負載多個例項的快速設定。

--latency-mode

布林值

呼叫延遲模式基準測試的快速設定,其中使用所有物理核心,每個例項使用 4 個核心。

--throughput-mode

布林值

呼叫吞吐量模式基準測試的快速設定,其中使用所有物理核心,每個例項使用 1 個 numa 節點。

--disable-numactl

布林值

預設情況下,numactl 命令用於控制 NUMA 訪問。設定此標誌將停用它。

--disable-taskset

布林值

停用 taskset 命令的使用。

注意

此指令碼將設定的環境變數包括以下內容

環境變數

LD_PRELOAD

根據您設定的 knobs,可能會將 <lib>/libiomp5.so、<lib>/libjemalloc.so、<lib>/libtcmalloc.so 追加到 LD_PRELOAD。

KMP_AFFINITY

如果預載入了 libiomp5.so,KMP_AFFINITY 可以設定為 "granularity=fine,compact,1,0"

KMP_BLOCKTIME

如果預載入了 libiomp5.so,KMP_BLOCKTIME 將設定為“1”。

OMP_NUM_THREADS

ncores_per_instance 的值

MALLOC_CONF

如果預載入了 libjemalloc.so,MALLOC_CONF 將設定為 "oversize_threshold:1,background_thread:true,metadata_thp:auto"

請注意,指令碼會尊重預先設定的環境變數。例如,如果您在執行指令碼之前設定了上述環境變數,則指令碼不會覆蓋這些變數的值。

結論#

在本教程中,我們探討了旨在最佳化 Intel® Xeon® 可擴充套件處理器上 PyTorch 推理效能的各種高階配置和工具。透過利用 torch.backends.xeon.run_cpu 指令碼,我們演示瞭如何微調執行緒和記憶體管理以實現最佳效能。我們涵蓋了 NUMA 訪問控制、TCMallocJeMalloc 等最佳化記憶體分配器以及使用 Intel® OpenMP 進行高效多執行緒處理等基本概念。

此外,我們提供了實用的命令列示例,指導您完成單例項和多例項場景的設定,確保針對特定工作負載最佳化資源利用率。透過理解和應用這些技術,使用者可以顯著提高其 PyTorch 應用程式在 Intel® Xeon® 平臺上的效率和速度。

另請參閱