与openmp中的线程数相关的性能

时间:2015-12-21 21:19:55

标签: c parallel-processing openmp

我使用OpenMP编写了一个小矩阵乘法程序。当我使用2个线程时,我获得最佳性能,当我使用1000个线程时,性能最差。 我有64个处理器。当数字线程在1或2时,我获得最佳性能。

    ~/openmp/mat_mul>  cat /proc/cpuinfo | grep processor | wc -l
    64
    ~/openmp/mat_mul> export OMP_NUM_THREADS=2
    ~/openmp/mat_mul> time ./main 
    Total threads : 2
    Master thread initializing

    real    0m1.536s
    user    0m2.728s
    sys     0m0.200s
    ~/openmp/mat_mul> export OMP_NUM_THREADS=64
    ~/openmp/mat_mul> time ./main 
    Total threads : 64
    Master thread initializing

    real    0m25.755s
    user    4m34.665s
    sys     21m5.595s

这是我的矩阵乘法代码。

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>

#define ROW_SIZE_A 100
#define COL_SIZE_A 5000
#define COL_SIZE_B 300

int get_random();

int main(int argc, char* argv[])
{
        int a[ROW_SIZE_A][COL_SIZE_A];
        int b[COL_SIZE_A][COL_SIZE_B];
        int c[ROW_SIZE_A][COL_SIZE_B];
        int i,j,k, tid, thread_cnt;

        srand(time(NULL));

        #pragma omp parallel shared(a,b,c,thread_cnt) private(i,j,k,tid)
        {
                tid = omp_get_thread_num();
                if(tid == 0)
                {
                        thread_cnt = omp_get_num_threads();
                        printf("Total threads : %d\n", thread_cnt);
                        printf("Master thread initializing\n");
                }
                #pragma omp parallel for schedule(static) 
                for(i=0; i<ROW_SIZE_A; i++)
                {
                        for(j=0; j<COL_SIZE_A; j++)
                        {
                                a[i][j] = get_random();
                        }
                }
               #pragma omp parallel for schedule(static) 
                for(i=0; i<COL_SIZE_A; i++)
                {
                        for(j=0; j<COL_SIZE_B; j++)
                        {
                                b[i][j] = get_random();
                        }
                }
                #pragma omp parallel for schedule(static)
                for(i=0; i<ROW_SIZE_A; i++)
                {
                        for(j=0; j<COL_SIZE_B; j++)
                        {
                                c[i][j] = 0;
                        }
                }

                #pragma omp barrier

                #pragma omp parallel for schedule(static) 
                for(i=0; i<ROW_SIZE_A; i++)
                {
                        for(j=0; j<COL_SIZE_B; j++)
                        {
                                c[i][j] = 0;
                                for(k=0; k<COL_SIZE_A; k++)
                                {
                                        c[i][j] += a[i][k] + b[k][j];
                                }
                        }
                }

        }

        return 0;


}

有人可以告诉我为什么会这样吗?

2 个答案:

答案 0 :(得分:2)

由于使用了错误的OpenMP构造,因此for循环未正确并行化。 parallel for是一个组合指令,它既创建了一个新的并行区域,又在其中嵌入了for工作共享结构。然后,循环的迭代在内部区域的线程之间分配。因此,您有64个线程,每个线程完整地运行所有循环,并在c上同时写入。除了产生错误答案外,它还会对所观察到的性能产生灾难性后果。此外,默认情况下,嵌套区域以串行方式执行,除非通过调用omp_set_nested(1);或通过适当设置OMP_NESTED环境变量明确启用嵌套并行性。

从并行区域内的所有for循环中删除parallel关键字:

    #pragma omp parallel shared(a,b,c,thread_cnt) private(i,j,k,tid)
    {
        ...
        #pragma omp parallel for schedule(static)
                    ^^^^^^^^ 
        for(i=0; i<ROW_SIZE_A; i++)
        {
           ...
        }
        ...
    }

应该成为

    #pragma omp parallel shared(a,b,c,thread_cnt) private(i,j,k,tid)
    {
        ...
        #pragma omp for schedule(static) 
        for(i=0; i<ROW_SIZE_A; i++)
        {
           ...
        }
        ...
    }

这将启用外部区域的线程之间的循环迭代的工作共享按预期进行。

答案 1 :(得分:0)

通常,您的处理器只能并行运行固定数量的线程。增加超过该数量的线程数不会加速您的程序。实际上,大量的线程导致了周到的调度开销,从而减慢了计算速度。

还要记住Amdahl's law,并行性只能提高你的表现。