OpenMP基准测试:我做得对吗?

我制作了一个计算斐波纳契序列的程序。 我用不同数量的线程(例如,1,2,10)执行它,但执行时间几乎保持不变(约0.500秒)。

我在Ubuntu和GNU GCC编译器上使用CodeBlocks。 在CodeBlocks中,我链接了库gomp并为编译器定义了标志-fopenmp

 #include  #include  #include  int main() { int i, n=1000, a[n]; omp_set_num_threads(4); for(i=0; i<n; i++) { a[i] = 1 + (rand() % ( 50 - 1 + 1 ) ); } fibo(n, a); return 0; } void fibo(int sizeN, int n[]) { int i; #pragma omp parallel for for(i=0; i<sizeN; i++) { int a = 0, b = 1, next, c; printf("n = %i\n", n[i]); for (c=0; c<=n[i]; c++) { if (c <= 1) { next = c; } else { next = a + b; a = b; b = next; } printf("%d\n",next); } } } 

有人有想法吗?
如何确保OpenMP真正起作用(已安装)?

删除两个printf语句。 您的程序花费更多时间将文本发送到标准输出而不是计算数字。 由于标准输出基本上是串行的,因此您的程序在printf语句中序列化。 更不用说printf本身的开销 – 它必须解析格式字符串,将整数值转换为字符串,然后将其发送到stdout流。

观察那些测量时间( n = 10000 ):

 OMP_NUM_THREADS=1 ./fibo.exe 0.10s user 0.42s system 40% cpu 1.305 total ^^^^^^^^^^^^ OMP_NUM_THREADS=2 ./fibo.exe 0.24s user 1.01s system 95% cpu 1.303 total ^^^^^^^^^^^^ OMP_NUM_THREADS=4 ./fibo.exe 0.36s user 1.87s system 163% cpu 1.360 total ^^^^^^^^^^^^ 

我已经删除了对omp_set_num_threads()的调用,而是使用OMP_NUM_THREADS ,这允许运行具有不同线程数的程序而无需重新编译源代码。 请注意,该程序在系统模式下的使用时间始终比用户模式多4倍。 这是该文本输出的开销。

现在比较两个被注释掉的printf语句(注意我必须将n增加到1000000以便从time获得有意义的结果):

 OMP_NUM_THREADS=1 ./fibo.exe 0.20s user 0.00s system 99% cpu 0.208 total ^^^^^^^^^^^ OMP_NUM_THREADS=2 ./fibo.exe 0.21s user 0.00s system 179% cpu 0.119 total ^^^^^^^^^^^ OMP_NUM_THREADS=4 ./fibo.exe 0.20s user 0.01s system 295% cpu 0.071 total ^^^^^^^^^^^ 

现在系统时间几乎保持为零,程序比2个线程快1,75倍,4个线程快2,93倍。 加速不是线性的,因为螺纹之间的工作分布存在轻微的不平衡。 如果数组填充了常数值,则加速几乎是线性的。

尝试要求更大的常数 (非随机)的fibbonacci值,以及更大的sizeN值。 然后,您应该使用相同的值进行测试,但使用串行实现(删除#pragma并再次编译)。

此外,您的系统中应该有多个核心,以便从并行性中获得一些好处。

最后,如果它通过-fopenmp编译,则安装OpenMP。