我在C ++程序中使用OpenMP。根据gcc文档,默认调度为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;
}
我使用MSYS2的mingw版本(gcc 9.3.0)编译了代码,没有进行优化,并且启用了-g
。如文档中所述,默认计划为dynamic, 1
。但是,我计算机上的计算时间为(具有2个线程):
schedule(static)
:〜2.103s schedule(dynamic, 1)
:〜24.096s schedule
(应为dynamic, 1
):〜2.101s 因此默认的时间表似乎是static
!我知道我在问一个非常具体的问题,但这是预期的行为吗?
答案 0 :(得分:2)
OMP_SCHEDULE
和omp_set_schedule()
影响运行时循环调度,即for
带有schedule(runtime)
子句的构造。在大多数OpenMP运行时中,不存在schedule
子句时的默认调度为static
,其块大小等于#iterations / #threads
(处理#threads
不除{ {1}}是特定于实现的,但是其余的迭代通常分布在前#iterations
个线程上。在这种情况下,考虑到开销,没有明智的OpenMP供应商会选择#iterations % #threads
作为默认设置。
答案 1 :(得分:-1)
p 22:3.12 OMP_SCHEDULE –如何调度线程描述:允许指定调度类型和块大小。变量的值应采用以下形式:type [,chunk],其中type是静态,动态,引导或自动之一。可选的块大小应为正整数。如果未定义,则使用动态调度且块大小为1。
您引用的这一部分是关于环境变量的。如果未定义环境变量,则使用动态调度和块大小为1。在您的代码中,您不会检查该环境变量的值或存在性,而只会检查实际的调度策略。如果您确实检查了环境变量,那么我希望它确实存在并且设置为静态。具体操作方式取决于操作系统(在Linux中为printenv
)。