Search code examples
c++gccopenmp

Default scheduling in OpenMP (gcc compiler)


I am using OpenMP in a C++ progam. According to the gcc documentation, the default scheduling is dynamic with a chunk size of 1 -> https://gcc.gnu.org/onlinedocs/gcc-9.3.0/libgomp.pdf (p22).

I decided to test this so I wrote a simple C++ test program:

#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;
}

I compiled the code using MSYS2's mingw version (gcc 9.3.0) with no optimisations and -g enabled. The default schedule is dynamic, 1 as in the documentation. However, the computation times on my computer are (with 2 threads):

  • with schedule(static) : ~2.103s
  • with schedule(dynamic, 1) : ~24.096s
  • omitting schedule (should be dynamic, 1) : ~2.101s

So that the default schedule seems to be static! I know I am asking a very specific question, but is it an intended behaviour ?


Solution

  • OMP_SCHEDULE and omp_set_schedule() affect runtime loop scheduling, that is for constructs with schedule(runtime) clause. With most OpenMP runtimes, the default scheduling when no schedule clause is present is static with chunk size equal to #iterations / #threads (the handling of the case where #threads does not divide #iterations is implementation-specific, but usually the remainder of the iterations is spread over the first #iterations % #threads threads). No sane OpenMP vendor would choose dynamic,1 as the default in that case, given the overhead it entails.