无法解释的不同omp_get_wtime()用于相同的精确计算

时间:2019-05-14 19:43:59

标签: c++ c openmp

我正在Visual Studio(实际上是C ++)中编写代码,并且我意识到在并行运行特定功能(仅进行基本矩阵乘法)时,在相同条件下进行不同运行所花费的计算时间会大大不同。 / p>

具有以下令人困惑的输出: 1 /第一次运行并行化函数时,omg_get_wtime()提供了比串行版本高的计算时间 2 /随后的时间,我称之为计算时间。 我的问题是:同一个函数为什么会在第一时间给出不同的时间(即,第一次运行与随后的运行给出的时间完全不同...)

#include<iostream>
#include<conio.h>
#include<iomanip>
#include<omp.h>
#include<stdlib.h>

using namespace std;

const int ROW = 50;
const int COL = 50; 

class matmul
{
    int a[ROW][COL];
    int row;
    int col;
    //int* prow;
public:
    matmul() : row(0), col(0) {} 
    ~matmul() {} 
    void display();
    matmul multiply_par1(matmul m1, matmul m2);


    void generate_matrix(int row, int col);
};



void matmul::display()
{
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
            cout << setw(5) << a[i][j];
        cout << endl;
    }
}




matmul matmul::multiply_par1(matmul m1, matmul m2)
{
    int i = 0;
    int j = 0;
    int k = 0;
    matmul temp;
    temp.row = m1.row;
    temp.col = m2.col;
    double st = omp_get_wtime();
    int nbr = m1.row;
    int nbc = m2.col;

#pragma omp parallel private( i, j, k) // shared(nbr,nbc)
    for (i = 0; i < nbr; i++)
        for (j = 0; j < nbc; j++)
        {
            temp.a[i][j] = 0;
            {
                for (k = 0; k < temp.col; k++)
               temp.a[i][j] += m1.a[i][k] * m2.a[k][j];
            }
        }
    double en = omp_get_wtime();
    printf("Parallel run: %lf\n", en - st);
    return temp;
}



void matmul::generate_matrix(int r, int c)
{
    //matrix temp;
    row = r;
    col = c;
    for (int i = 0; i < row; i++)
        for (int j = 0; j < col; j++)
        {
            a[i][j] = rand() % 10;
        }

}


int main()
{
    int Size = 10;
    int* arr = new int[Size];
    matmul m1, m2, m3, m4, m5,m6,m7;
    int r1, c1;

    if (Size > 100)
    {
        cout << "matrix quite large to display...\n";
    }
    else
    {
        cout << "Generating 1rst matrix...\n";
        m1.generate_matrix(10, 10);
        m1.display();
        cout << "Generating 2nd matrix...\n";
        m2.generate_matrix(10, 10);
        m2.display();



        m4 = m3.multiply_par1(m1, m2);
        cout << "Resultant parallel matrix is :\n";
        //m5.display();

        m5 = m3.multiply_par1(m1, m2);
        cout << "Resultant parallel matrix is :\n";
        //m6.display();


        m6 = m3.multiply_par1(m1, m2);
        cout << "Resultant parallel matrix is :\n";
        //m6.display();

        m7 = m3.multiply_par1(m1, m2);
        cout << "Resultant parallel matrix is :\n";
        //m6.display();



    }

    return 0;
}

我希望运行时间完全相同,但是第一个是明显不同的。执行时得到以下输出:

Parallel running time: 0.000583
Resultant parallel matrix is :
Parallel running time: 0.000016
Resultant parallel matrix is :
Parallel running time: 0.000014
Resultant parallel matrix is :
Parallel running time: 0.000014
Resultant parallel matrix is :

您看到的0.000583确实不合适,我也不明白为什么...

至关重要的是,在上面的代码仅使用一次的情况下(例如500x500矩阵),我们是否可以对代码进行改进以产生更好的wtime()?

1 个答案:

答案 0 :(得分:4)

OpenMP必须在执行并行节(details)之前创建线程。创建线程需要时间,这是您在第一次测量中所观察到的。

但是,OpenMP实现不会在并行区域之间创建新的线程,因为它使用线程池(回收先前创建的线程)。这就是为什么后续测量要好得多的原因。

在您的情况下,矩阵很小,因此线程创建的开销掩盖了多线程的优点。但是,对于后续调用,使用多线程可能仍然是有益的。因此,请始终测量第一个,第二个和总平均值,以确保从长远来看值得并行执行代码。