我可以报告openmp任务的进度吗? [英] Can I report progress for openmp tasks?
问题描述
想象一个经典的OMP任务:
Imagine a classic OMP task:
- 对范围为[0.0,1.0)的double的大向量求和
using namespace std;
int main() {
vector<double> v;
// generate some data
generate_n(back_inserter(v), 1ul << 18,
bind(uniform_real_distribution<double>(0,1.0), default_random_engine { random_device {}() }));
long double sum = 0;
{
#pragma omp parallel for reduction(+:sum)
for(size_t i = 0; i < v.size(); i++)
{
sum += v[i];
}
}
std::cout << "Done: sum = " << sum << "\n";
}
我很难想出如何报告进度的想法.毕竟,OMP正在为我处理团队线程之间的所有协调,而我没有一个全局状态.
I have trouble coming up with an idea how to report progress. After all, OMP is handling all the coordination between team threads for me, and I don't have a piece of global state.
我可能会使用常规的std::thread
并从那里观察一些共享变量,但是难道没有实现这种目标的麻烦"方法吗?
I could potentially use a regular std::thread
and observe some shared variable from there, but isn't there a more "omp-ish" way to achieve this?
推荐答案
只需让团队中的每个线程跟踪本地进度并自动更新全局计数器.您仍然可以让另一个线程对其进行观察,或者,如下面的示例所示,您可以只在OMP关键部分内进行终端输出.
Just let each thread in the team track local progress and update a global counter atomically. You could still make another thread observe it, or, as in my sample below, you could just do the terminal output within an OMP critical section.
此处的关键是调整不会导致频繁更新的逐步大小,因为对关键区域(以及较小程度的原子加载/存储)的锁定会降低性能. /em>
The key here is to tune for a stepsize that doesn't lead to highly frequent updates, because then the locking for the critical region (and to a lesser extent the atomic load/stores) would degrade performance.
#include <omp.h>
#include <vector>
#include <random>
#include <algorithm>
#include <iterator>
#include <functional>
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
vector<double> v;
// generate some data
generate_n(back_inserter(v), 1ul << 18, bind(uniform_real_distribution<double>(0,1.0), default_random_engine { random_device {}() }));
auto step_size = 100ul;
auto total_steps = v.size() / step_size + 1;
size_t steps_completed = 0;
long double sum = 0;
#pragma omp parallel
{
size_t local_count = 0;
#pragma omp for reduction(+:sum)
for(size_t i = 0; i < v.size(); i++)
{
sum += v[i];
if (local_count++ % step_size == step_size-1)
{
#pragma omp atomic
++steps_completed;
if (steps_completed % 100 == 1)
{
#pragma omp critical
std::cout << "Progress: " << steps_completed << " of " << total_steps << " (" << std::fixed << std::setprecision(1) << (100.0*steps_completed/total_steps) << "%)\n";
}
}
}
}
std::cout << "Done: sum = " << sum << "\n";
}
最后,打印结果.输出:
Finally, print the result. Output:
Progress: 1 of 2622 (0.0%)
Progress: 191 of 2622 (7.3%)
Progress: 214 of 2622 (8.2%)
Progress: 301 of 2622 (11.5%)
Progress: 401 of 2622 (15.3%)
Progress: 501 of 2622 (19.1%)
Progress: 601 of 2622 (22.9%)
Progress: 701 of 2622 (26.7%)
Progress: 804 of 2622 (30.7%)
Progress: 901 of 2622 (34.4%)
Progress: 1003 of 2622 (38.3%)
Progress: 1101 of 2622 (42.0%)
Progress: 1201 of 2622 (45.8%)
Progress: 1301 of 2622 (49.6%)
Progress: 1402 of 2622 (53.5%)
Progress: 1501 of 2622 (57.2%)
Progress: 1601 of 2622 (61.1%)
Progress: 1701 of 2622 (64.9%)
Progress: 1801 of 2622 (68.7%)
Progress: 1901 of 2622 (72.5%)
Progress: 2001 of 2622 (76.3%)
Progress: 2101 of 2622 (80.1%)
Progress: 2203 of 2622 (84.0%)
Progress: 2301 of 2622 (87.8%)
Progress: 2402 of 2622 (91.6%)
Progress: 2501 of 2622 (95.4%)
Progress: 2601 of 2622 (99.2%)
Done: sum = 130943.8
这篇关于我可以报告openmp任务的进度吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!