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。