在调查代码的性能问题后,我意识到在“隔离核心”上运行的基于 OpenMP 的并行代码将线程数限制为单个核心。 此代码应将 for 循环展开到 N 个核心(例如
$OMP_NUM_THREADS=N
):
// g++ -fopenmp -I/usr/include/ -03 test_openmp.cpp -o testomp
#include <immintrin.h>
#include <cmath>
#include <chrono>
#include <iostream>
const float nano = 1000000000;
int main(){
std::size_t niter = 10000000000;
auto start = std::chrono::system_clock::now();
#pragma omp parallel for
for(std::size_t i = 0; i < niter; i++){
std::size_t x = sqrt(i);
}
auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now() - start);
std::cout << "Took " << elapsed.count()/nano << " s" << std::endl;
}
在我的开发系统上,有 32 个核心; 0-15 是孤立的,而 16-31 不是孤立的。 在隔离的核心上运行代码给出:
OMP_NUM_THREADS=4 taskset -c 0-3 ./testomp
Took 5.33671 s
在非隔离核心上
OMP_NUM_THREADS=4 taskset -c 16-19 ./testomp
Took 1.33193 s
此外,
htop
显示隔离 CPU 测试中 1 个 100% 利用率的核心,而非隔离 CPU 测试显示 4 个 CPU 核心 100% 利用率。
有没有办法允许 OpenMP 在并行 for 循环中使用多个隔离内核?出于性能原因(避免内核任务等),使用隔离内核至关重要。
如果不是,OpenMP 如何区分隔离核和非隔离核?
编辑我使用
-0 3
启用了优化。当然,执行时间会减少,但这不是重点(也不是基准测试)。关键是代码运行在多个非隔离内核上,但只运行在一个隔离内核上。但是,在隔离核心上,我看到有四个线程正在运行。
我正在使用 GNU C++ 编译器:~$ g++ --version
g++ (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
OpenMP版本是4.5
CPU及其配置:
~$ lscpu
lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
Address sizes: 52 bits physical, 57 bits virtual
CPU(s): 128
On-line CPU(s) list: 0-63
Off-line CPU(s) list: 64-127
Thread(s) per core: 1
Core(s) per socket: 32
Socket(s): 2
NUMA node(s): 2
Vendor ID: AuthenticAMD
CPU family: 25
Model: 17
Model name: AMD EPYC 9354 32-Core Processor
Stepping: 1
Frequency boost: enabled
CPU MHz: 1499.458
CPU max MHz: 3799.0720
CPU min MHz: 1500.0000
BogoMIPS: 6499.69
Virtualization: AMD-V
L1d cache: 2 MiB
L1i cache: 2 MiB
L2 cache: 64 MiB
L3 cache: 512 MiB
NUMA node0 CPU(s): 0-31