我构建了一个数据分析软件,我试图保持功能简短,如果可能的话没有副作用。然后我使用OpenMP在可能的情况下并行化for
- 循环。这很有效,除了进度不可见。
然后我引入了像if (i % 10 == 0) print_status(i);
之类的语句来在循环中给出状态消息。由于所有操作都需要大约相同的时间,因此我没有更改OpenMP调度策略,该策略只是将循环范围划分为多个块并将每个块分配给一个线程。然后输出将是
0
100
200
10
110
210
…
这对用户没有多大帮助。我可以更改调度策略,使元素按顺序粗略处理,但这会带来实际工作不需要的同步成本。它甚至可能使prefetcher更难,因为每个线程的循环索引不再是连续的。
这个问题更糟糕,因为我有一个昂贵的功能,需要几分钟才能完成。我并行运行其中三个。所以我有
#pragma omp parallel for
for (int i = 0; i < 3; ++i) {
result[i] = expensive(i);
}
目前,函数expensive
只会打印出类似“正在i = 0
上工作,而我在56%”的内容。这将输出交错(行,我使用omp critical
和std::cout
)与其他三个正在运行的实例。判断系统的整体进度并不容易,也有点麻烦。
我想我可以通过将一个仿函数传递给expensive
函数来解决这个问题,然后可以使用当前状态调用该函数。仿函数将了解expensive
个实例的数量,并可以计算全局进度。根据调度策略,进度条需要有多个活动部分,就像BitTorrent下载一样。但是,只需完成工作与总工作的比例就是一个很好的特征。
这将使所有长时间运行的函数的接口复杂化,我不确定这是否真的值得它带来的复杂性。
在不引入副作用的情况下,可能无法从函数中获取状态信息。我只是不想为了统一的进度信息而难以维护代码。
有没有明智的方法可以做到这一点而不会给系统增加更多的复杂功能?