我正在研究如何将一些现有的C ++代码从基于线程的迁移迁移到基于任务的并行性,以及是否需要迁移。这是我的情景:
假设我有一些函数可以在事件上执行。假设我有一个摄像头,每次一帧到达时我想做一些繁重的处理并保存结果。一些处理是串行的,所以如果我只是在同一个线程中串行处理每个帧,我就不会获得完整的CPU利用率。假设帧每33毫秒到达一帧,帧的处理延迟接近100毫秒。
因此,在我当前的实现中,我创建了3个线程来处理帧并将每个新帧分配给循环中的这些工作线程之一。因此,线程T0可能会处理帧F0,F3,F6等。现在我获得了完整的CPU利用率,并且我不必丢帧以保持实时速率。
由于处理需要各种大的临时资源,我可以为每个工作线程预先分配这些资源。因此,不必为每一帧重新分配它们。这种每线程资源的策略适用于粒度:如果它们是按帧分配的,这将花费太长时间,但是如果有更多的工作线程,我们就会耗尽资源。
我没有看到使用标准C ++ 11或Microsoft的PPL库将这种基于线程的并行性替换为基于任务的并行性的方法。如果有这样做的模式可以在下面勾勒出来,我会非常乐意学习它。
问题是存储状态的位置 - 分配的临时资源(例如GPU内存) - 可以重复用于后续帧,但不得与当前处理帧的资源冲突。
在这种情况下,是否甚至需要迁移到基于任务的并行性?
答案 0 :(得分:0)
我想出来了。这是一个示例解决方案:
#include <iostream>
#include <ppltasks.h>
#include <thread>
#include <vector>
using PipelineState = int;
using PipelineStateArg = std::shared_ptr<PipelineState>;
using FrameState = int;
struct Pipeline
{
PipelineStateArg state;
concurrency::task<void> task;
};
std::vector<Pipeline> pipelines;
void proc(const FrameState& fs, PipelineState& ps)
{
std::cout << "Process frame " << fs << " in pipeline " << ps << std::endl;
}
void on_frame(int index)
{
FrameState frame = index;
if (index < 2)
{
// Start a new pipeline
auto state = std::make_shared<PipelineState>(index);
pipelines.push_back({state, concurrency::create_task([=]()
{
proc(frame, *state);
})});
}
else
{
// Use an existing pipeline
auto& pipeline = pipelines[index & 1];
auto state = pipeline.state;
pipeline.task = pipeline.task.then([=]()
{
proc(frame, *state);
});
}
}
void main()
{
for (int i = 0; i < 100; ++i)
{
on_frame(i);
std::this_thread::sleep_for(std::chrono::milliseconds(33));
}
for (auto& pipeline : pipelines)
pipeline.tail.wait();
}