Необъяснимые разные omp_get_wtime () для одного и того же точного вычисления - PullRequest
3 голосов
/ 14 мая 2019

Я пишу код в Visual Studio (на самом деле C ++) и понял, что при выполнении конкретной функции параллельно (просто при базовом умножении матриц) время выполнения вычислений сильно отличается при разных запусках в одинаковых условиях.

имеет следующий удивительный вывод: 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 Ответ

4 голосов
/ 14 мая 2019

OpenMP должен создать потоки перед выполнением параллельной секции ( details ). Создание потоков требует времени, и это то, что вы наблюдаете в своем первом измерении.

Однако реализации OpenMP не создают новые потоки между параллельными областями, потому что он использует пул потоков (он перерабатывает ранее созданные потоки). Вот почему последующие измерения намного лучше.

В вашем случае матрицы довольно малы, поэтому преимущества многопоточности затеняются накладными расходами на создание потоков. Для последующих вызовов, однако, все еще может быть полезно использовать многопоточность. По этой причине всегда измеряйте первое, последующее и общее среднее значение, чтобы гарантировать, что фрагмент кода стоит распараллеливать в долгосрочной перспективе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...