c++ - OpenMP 中的默认调度(gcc 编译器)
问题描述
我在 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
!我知道我在问一个非常具体的问题,但这是一种预期的行为吗?
解决方案
OMP_SCHEDULE
并omp_set_schedule()
影响运行时循环调度,即for
带有schedule(runtime)
子句的构造。对于大多数 OpenMP 运行时,不存在schedule
子句时的默认调度是static
块大小等于(不除#iterations / #threads
的情况的处理是特定于实现的,但通常剩余的迭代分布在第一个线程上)。在这种情况下,没有理智的 OpenMP 供应商会选择默认设置,因为它会带来开销。#threads
#iterations
#iterations % #threads
dynamic,1
推荐阅读
- java - 运算符 switchMap() 不会取消订阅上一个请求
- c++ - 如何从用户输入中替换代码中的变量值?
- php - php验证散列密码在我的函数中不起作用
- android - 如何将 Piniew OTP 字段设计从方框更改为简单线?
- ios - 动态改变 cell.update 日期函数?
- mysql - MySQL Server 基于线程而不是基于进程是什么意思?
- spring - Junit 用一堆@Pointcut 测试一个类
- django - 如何修复在 EC2 上运行的 Django 实例中更高的内存利用率,是否由于 gunicorn.sock 的多个运行进程?
- html - 如何在背景颜色之上设置背景图像
- algorithm - 这个迷宫生成算法叫什么名字?