Как оценить многопараметрическую функцию с использованием OpenMP - PullRequest
0 голосов
/ 24 сентября 2019

Так что я довольно новичок в OpenMP, но недавно я начал играть с ним, и теперь я хочу использовать его, чтобы «ускорить» некоторые вычисления, которые мне нужно сделать.У меня есть функция, которая зависит от 3 переменных, и я хочу оценить ее в некоторых точках интервала, а затем показать значения в файле.Дело в том, что интервалы для 3-х параметров довольно большие, поэтому у меня будет много оценок функций.Использование 3-вложенного цикла for довольно сложно, если мой интервал большой.

Последовательная реализация прямолинейна, просто создайте 3-вложенный цикл, где каждый индекс i, j, k принимает значениесоответствующий параметр (целые числа от 1 до DIM и оценка функции в точке (i, j, k). В подходе OpenMP я, очевидно, думал об использовании #pragma omp parallel for в надежде, что время выполнения программы будет быстрее.

Вот код, который я написал для последовательной реализации, и "параллельный". Пожалуйста, имейте в виду, что DIM установлен здесь на меньшее число только для целей тестирования.

#include <iostream>
#include <chrono>
#include <omp.h>
#include <cmath>
#include <fstream>

using namespace std;

ofstream outparallel("../output/outputParallel.dat");
ofstream outserial("../output/outputSerial.dat");

const int spaceDIM = 80;

double myFunction(double a, double b, double c)
{
    return (double)a * log(b) + exp(a / b) + c;
}

void serialAlgorithmTripleLoop()
{
    auto sum = 0;
    auto timeStart = chrono::high_resolution_clock::now();
    for (int i = 1; i <= spaceDIM; ++i)
        for (int j = 1; j <= spaceDIM; ++j)
            for (int k = 1; k <= spaceDIM; ++k)
            {
                //sum += i * j * k;
                outserial << i << " " << j << " " << k << " " << myFunction((double)i, (double)j, (double)k) << endl;
            }
    auto timeStop = chrono::high_resolution_clock::now();
    auto execTime = chrono::duration_cast<chrono::seconds>(timeStop - timeStart).count();
    cout << "Serial execution time = " << execTime << " seconds";
    cout << endl;
    outserial << "Execution time = " << execTime << " seconds";
    outserial << endl;
}

void parallelAlgorithmTripleLoop()
{
    //start of the actual algorithm
    auto sum = 0;
    auto timeStart = chrono::high_resolution_clock::now();
#pragma omp parallel for
    for (int i = 1; i <= spaceDIM; ++i)
        for (int j = 1; j <= spaceDIM; ++j)
            for (int k = 1; k <= spaceDIM; ++k)
            {
                //   sum += i * j * k;
                outparallel << i << " " << j << " " << myFunction((double)i, (double)j, (double)k) << endl;
            }
    auto timeStop = chrono::high_resolution_clock::now();
    auto execTime = chrono::duration_cast<chrono::seconds>(timeStop - timeStart).count();
    cout << "Parallel execution time = " << execTime << " seconds";
    cout << endl;
    outparallel << "Execution time = " << execTime << " seconds";
    outparallel << endl;
}

int main()
{
    cout << "FUNCTION OPTIMIZATION" << endl;
    serialAlgorithmTripleLoop();
    parallelAlgorithmTripleLoop();
    return 0;
}

ВыводДля меня это неожиданно: используя параллельный подход, я получаю больше времени выполнения, чем последовательный. Я также пытался использовать предложения «сокращение» и «упорядоченный» и «свернутый» из стандарта OMP, но ни один из них не помог мне.на 4-ядерном 8-потоковом ноутбуке.

FUNCTION OPTIMIZATION
Serial execution time = 4 seconds
Parallel execution time = 7 seconds

В: Как правильно ускорить оценку функции?

...