【发布时间】:2014-03-24 11:46:16
【问题描述】:
为了更好的可读性,我在之前的 cmets(尤其是 @Zboson)之后编辑了我的问题
我一直遵循并观察到,openmp 线程的数量应与机器上的超线程数量大致匹配以获得最佳性能的传统观念。但是,我在配备 Intel Core i7 4960HQ、4 核 - 8 线程的新笔记本电脑上观察到异常行为。 (见Intel docs here)
这是我的测试代码:
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
int main() {
const int n = 256*8192*100;
double *A, *B;
posix_memalign((void**)&A, 64, n*sizeof(double));
posix_memalign((void**)&B, 64, n*sizeof(double));
for (int i = 0; i < n; ++i) {
A[i] = 0.1;
B[i] = 0.0;
}
double start = omp_get_wtime();
#pragma omp parallel for
for (int i = 0; i < n; ++i) {
B[i] = exp(A[i]) + sin(B[i]);
}
double end = omp_get_wtime();
double sum = 0.0;
for (int i = 0; i < n; ++i) {
sum += B[i];
}
printf("%g %g\n", end - start, sum);
return 0;
}
当我使用gcc 4.9-4.9-20140209 编译它时,使用命令:gcc -Ofast -march=native -std=c99 -fopenmp -Wa,-q 当我更改OMP_NUM_THREADS 时,我看到了以下性能[这些点是5 次运行的平均值,误差线(几乎不可见)是标准偏差]:
当显示为相对于 OMP_NUM_THREADS=1 的加速时,情节更清晰:
性能或多或少随着线程数单调增加,即使 omp 线程数大大超过核心和超线程数!通常,当使用过多线程时(至少在我以前的经验中),由于线程开销,性能应该会下降。尤其是计算应该受 cpu(或至少是内存)限制,而不是等待 I/O。
更奇怪的是,加速是35倍!
谁能解释一下?
我还用更小的阵列 8192*4 对此进行了测试,并看到了类似的性能扩展。
如果重要的话,我在 Mac OS 10.9 上并且通过运行(在 bash 下)获得的性能数据:
for i in {1..128}; do
for k in {1..5}; do
export OMP_NUM_THREADS=$i;
echo -ne $i $k "";
./a.out;
done;
done > out
编辑:出于好奇,我决定尝试更多数量的线程。我的操作系统将此限制为 2000。奇怪的结果(加速和低线程开销)不言自明!
编辑:我在他们的回答中尝试了@Zboson 的最新建议,即将 VZEROUPPER 放在循环中的每个数学函数之前,它确实解决了缩放问题! (它还将单线程代码从 22 秒发送到 2 秒!):
【问题讨论】:
-
这可能是 OpenMP 分配线程的方式,您是否出于好奇尝试了 3 个线程?可能是当从 1 移动到 2 时,它会将两个线程分配给一个 ACTUAL 核心,但是因为您确实试图在该单一核心中利用相同的资源,所以它真的没有帮助!移动到 4 时,您实际上是在使用 2 个实际核心(也许)。另外,如果你使用 8 个线程会发生什么,所以我们可以看到当我们从(希望)超线程情况转移到全核心情况 + 超线程时会发生什么?
-
@trumpetlicks 我添加了你想要的时间。
-
另外,如果你要多次运行每个(除了单个案例),那么计时结果是多少。我认为 OpenMP 和操作系统随机分配给核心 #(或者在您的情况下,它可能分配给 HT 或实际核心)。
-
您在哪里更改编号。使用的线程数?
-
@Neuron 使用 OMP_NUM_THREADS 环境变量
标签: multithreading gcc parallel-processing openmp avx