Планирование по умолчанию в OpenMP (компилятор g cc) - PullRequest
0 голосов
/ 06 мая 2020

Я использую OpenMP в программе на C ++. Согласно документации g cc, планирование по умолчанию - dynamic с размером блока 1 -> https://gcc.gnu.org/onlinedocs/gcc-9.3.0/libgomp.pdf (p22).

Я решил проверить это, поэтому я написал простую тестовую программу на C ++:

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


int main()
{
    std::vector<double>  myArray {};
    for(std::size_t i {0} ; i < 100000000 ; ++i)
    {
        myArray.push_back(static_cast<double>(i));
    }

    #pragma omp parallel
    {
        if(omp_get_thread_num() == 0)
        {
            std::cout << "Number of threads = " << omp_get_num_threads() << "/" << omp_get_num_procs() << std::endl;
            omp_sched_t schedule {};
            int chunk_size {};
            omp_get_schedule(&schedule , &chunk_size);
            std::string scheduleStr {};
            switch(schedule)
            {
                case omp_sched_static:
                    scheduleStr = "static";
                    break;
                case omp_sched_dynamic:
                    scheduleStr = "dynamic";
                    break;
                case omp_sched_guided:
                    scheduleStr = "guided";
                    break;
                case omp_sched_auto:
                    scheduleStr = "auto";
                    break;
                default:
                    scheduleStr = "monotonic";
                    break;
            }
            std::cout << "Default schedule: " << scheduleStr << "," << chunk_size << std::endl;;
        }
    }

    auto startTime {std::chrono::high_resolution_clock::now()};
    #pragma omp parallel for default(shared) schedule(dynamic, 1)
    for(std::size_t i = 0 ; i < myArray.size() ; ++i)
    {
        myArray[i] = std::pow(myArray[i], 10);
    }
    auto endTime {std::chrono::high_resolution_clock::now()};
    auto ellapsedTime {std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime)};
    std::cout << "OMP for Time: " << static_cast<double>(ellapsedTime.count())/1000.0 << " s" << std::endl;

    return 0;
}

Я скомпилировал код, используя версию mingw MSYS2 (g cc 9.3.0) без оптимизации и -g. По умолчанию расписание dynamic, 1, как в документации. Однако время вычислений на моем компьютере (с 2 потоками):

  • с schedule(static): ~ 2,103 с
  • с schedule(dynamic, 1): ~ 24,096 с
  • без schedule (должно быть dynamic, 1): ~ 2,101 с

Таким образом, расписание по умолчанию выглядит как static! Я знаю, что задаю очень конкретный c вопрос, но это запланированное поведение?

Ответы [ 2 ]

2 голосов
/ 06 мая 2020

OMP_SCHEDULE и omp_set_schedule() влияют на время выполнения l oop планирование, то есть конструкции for с предложением schedule(runtime). В большинстве сред выполнения OpenMP планирование по умолчанию при отсутствии предложения schedule составляет static с размером блока, равным #iterations / #threads (обработка случая, когда #threads не делит #iterations, зависит от реализации c, но обычно оставшаяся часть итераций распределяется по первым #iterations % #threads потокам). Ни один здравомыслящий поставщик OpenMP не выбрал бы dynamic,1 по умолчанию в этом случае, учитывая накладные расходы, которые это влечет за собой.

0 голосов
/ 06 мая 2020

p 22: 3.12 OMP_SCHEDULE– Как планируются потоки Описание: позволяет указать тип расписания и размер блока. Значение переменной должно иметь вид: type [, chunk], где тип может быть одним из stati c, Dynami c, guided или auto. Необязательный размер блока должен быть положительным целым числом. Если не определено, используется динамическое c планирование и размер блока 1.

Этот раздел, который вы цитируете, посвящен переменным среды. Если переменная среды не определена, то используется планирование динамического c и размер блока, равный 1. В вашем коде вы не проверяете значение или существование этой переменной среды, а только действительную стратегию планирования. Если вы все же проверите свою переменную среды, я бы ожидал, что она существует и установлена ​​в stati c. Как это сделать, зависит от ОС (printenv в linux).

...