我使用了一个小测试程序来测试 OpenMP 的效率,以使用 mpfr/gmp 库使用任意精度并行化递归计算。正如预期的那样,OpenMP 开销一开始会使并行版本变慢,但使用足够的位后,并行版本会变得更快。
顺序循环如下:
....
for ( i = 0; i < 1000; i++ ) {
mpfr_set_d ( z1, 0.0, MPFR_RNDN );
mpfr_set_d ( z2, 0.0, MPFR_RNDN );
...
iter = 0;
while ( iter < 10000 ) {
mpfr_sqr ( tmp1, z1, MPFR_RNDN );
mpfr_sqr ( tmp2, z2, MPFR_RNDN );
mpfr_sub ( tr, tmp1, tmp2, MPFR_RNDN );
mpfr_add ( tr, tr, cr, MPFR_RNDN );
mpfr_mul_2si ( tmp3, z1, 1, MPFR_RNDN );
...
iter++;
}
}
和并行版本:
....
omp_set_dynamic(0);
for ( i = 0; i < 10; i++ ) {
mpfr_set_d ( z2, 0.0, MPFR_RNDN );
mpfr_set_d ( z1, 0.0, MPFR_RNDN );
...
iter = 0;
while ( iter < 10000 ) {
#pragma omp parallel num_threads(4)
{
switch ( omp_get_thread_num() ) {
case 0:
mpfr_sqr ( tmp1, z1, MPFR_RNDN );
mpfr_sqr ( tmp2, z2, MPFR_RNDN );
mpfr_sub ( tr, tmp1, tmp2, MPFR_RNDN );
mpfr_add ( tr, tr, cr, MPFR_RNDN ); break;
case 1:
mpfr_mul_2si ( tmp3, z1, 1, MPFR_RNDN );
mpfr_mul ( ti, tmp3, z2, MPFR_RNDN );
mpfr_add ( ti, ti, ci, MPFR_RNDN ); break;
...
mpfr_mul_2si ( tti, tti, 1, MPFR_RNDN ); break;
}
}
mpfr_set ( z1, tr, MPFR_RNDN );
mpfr_set ( z2, ti, MPFR_RNDN );
mpfr_set ( d1, ttr, MPFR_RNDN );
mpfr_set ( d2, tti, MPFR_RNDN );
iter++;
}
}
以秒为单位的运行时间系统 A:顺序
- 320 位:11
- 640 位:16
- 960 位:21
- 2560 位:60
- 5000 位:152
以秒为单位的运行时间系统 A:并行
- 320 位:15
- 640 位:16
- 960 位:18
- 2560 位:32
- 5000 位:65
以秒为单位的运行时间系统 B:顺序
- 320 位:13
- 640 位:18
- 960 位:27
- 2560 位:80
- 5000 位:202
以秒为单位的运行时间系统 B:并行
- 320 位:51
- 640 位:54
- 960 位:56
- 2560 位:76
- 5000 位:128
系统 A 是 Fedora 19 内核 3.11.10-200.fc19.x86_64
Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
系统 B 是 Linux Centos 6.5 内核 2.6.32-431.1.2.0.1.el6.x86_64
Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz
ltrace 显示被调用函数/系统调用的百分比大致相同。两个系统都使用最新的 gmp、mpfr 和 gcc 版本。为什么系统 B 比系统 A 差很多(例如,OpenMP 开销大很多倍)?Linux 内核在这方面变得更好了吗?任何内核参数等我应该看看?CPU硬件差异/限制?还有其他解释吗?我必须在 B 上安装 Fedora 19 来解决这个问题吗?
更新:感谢您的提示。它确实改变了系统 B 的结果。
以秒为单位的运行时间系统 B:并行
- 320 位:51 -> 23
- 640 位:54 -> 26
- 960 位:56 -> 29
- 2560 位:76 -> 47
- 5000 位:128 -> 99
B 仍然落后于 A,但差距已经小了很多。