【发布时间】:2012-12-10 10:44:06
【问题描述】:
上个月我一直在使用计算机矩阵乘法,并使用 openMP 和 eigen3 进行了一些测试。
测试是在以下机器上进行的:
计算机 1:
Intel Core i7-3610QM CPU @ 2,30GHz / 6 GB ddr3
计算机 2:
六核 AMD Opteron(tm) 处理器 2435 2.60 GHz(2 个处理器)/16 GB
对于 openMP,使用了以下矩阵-矩阵乘法算法:
void matrix4openmp(void)
{
int j;
#pragma omp parallel for
for (j=0;j<N; j+=2){
double v1[N],v2[N];
int i,k;
for (i=0;i<N; i++){
v1[i]=b[i][j];
v2[i]=b[i][j+1];
}
for (i=0; i<N;i+=2){
register double s00,s01,s10,s11;
s00=s01=s10=s11=0.0;
for (k=0;k<N;k++){
s00 += a[i] [k] * v1[k];
s01 += a[i] [k] * v2[k];
s10 += a[i+1][k] * v1[k];
s11 += a[i+1][k] * v2[k];
}
c[i] [j] =s00;
c[i] [j+1] =s01;
c[i+1][j] =s10;
c[i+1][j+1] =s11;
}
}
结果如下:
_______________计算机 1__________计算机 2
顺序________232,75600___________536,21400
OpenMP____________2,75764____________7,62024
特征3_____________3,35090____________1,92970
*时间以秒为单位。
*矩阵大小分别为 2700 x 2500 和 2500 x 2700。
*顺序算法与 OMP 不同,它是 m-m 乘法的最简单版本,可以在此处查看:http://pastebin.com/Pc9AKAE8。
*SSE2 指令已为 eigen3 测试激活。
*OpenMP 使用默认内核,这是 Windows 检测到的所有内核,包括虚拟内核。
如您所见,OpenMP 版本在第一台计算机 (i7) 上比 eigen3 版本更快。但是对于计算机 2(2x Opteron),eigen3 的性能完全胜过 OpenMP 版本以及在计算机 1 中进行的所有测试。
知道为什么我会得到这个结果,为什么 eigen3 在计算机 1 中的速度不如在计算机 2 中那么快吗?
【问题讨论】:
-
你能让所有的实现都使用 SSE2 吗? Opteron 有更多更快的内核用于原始内存时钟泵送,这使得这成为一个明显不平衡的测试。我建议至少均衡指令集(通过编译)和使用的内核数量。 (
taskset)。 -
@High Performance Mark 我忘了补充一点,顺序版本不使用我发布的相同算法,它使用最简单的版本,不使用任何优化。就是这个:pastebin.com/Pc9AKAE8 这就是为什么它可能要慢得多,因为它应该只使用内存而不是缓存和寄存器。
-
@Steve-o 我将尝试按顺序启用 SSE 和 OpenMP 并将其报告给您。使用的核心数是 openMP 的默认值,这是 windows 在每台机器中检测到的所有虚拟处理器(computer_1 中的 8 个,computer_2 中的 12 个)。当您的意思是“原始内存时钟泵送”时,您是在谈论 ram-cpu 数据传输吗?
-
@Steve-o 哪里有一些有趣的测试,所有测试都启用了相同数量的 CPU(4 个线程)和 SSE2:pastebin.com/mkWCicb7 现在这似乎更有意义了。似乎 i7 使用 8 个线程比使用 4 个线程要慢得多,因为它只有 4 个物理处理器。我可能会再次测试,将线程数设置为物理处理器的数量,而不是使用虚拟处理器进行计数。
-
您应该牢记以下几点: 1. Eigen3 使用 OpenMP 内置了矩阵-矩阵乘积的并行化(如果您使用 -fopenmp 编译它) 2. 应使用编译器编译 Eigen启用优化(-O2 或 -O3)并禁用断言(-DNDEBUG)。
标签: c++ multithreading performance matrix-multiplication eigen