我正在通过使其更加异步来改进应用程序(Win64、C++)。我正在使用并发运行时,到目前为止它对我来说效果很好。
该应用程序基本上执行许多“作业”转换数据。为了跟踪每个作业的功能,某些子系统配备了代码来跟踪作业执行的某些操作。以前,这将使用表示当前正在执行的作业的单个全局变量来注册跟踪信息,而无需将上下文信息一直传递到调用链中。每个作业也可以轮流使用 ConcRT 来并行化作业本身。这一切都很好。
不过,现在我正在重构应用程序,以便我们可以并行执行顶级作业。每个作业都作为 ConcRT 任务执行,这适用于除需要跟踪的作业之外的所有作业。
我基本上需要的是一种将一些上下文信息与任务相关联的方法,并将该流程流向由该任务产生的任何其他任务。基本上,我需要“任务本地”变量。
使用 ConcRT,我们不能简单地使用线程局部变量来存储上下文信息,因为该作业可能会使用 ConcRT 生成其他作业,并且这些作业将在任意数量的线程上执行。
我目前的方法包括在启动时创建许多调度程序实例,并在专用于该作业的调度程序中生成每个作业。然后我可以使用该Concurrency::CurrentScheduler::Id()
函数检索一个整数 ID,我可以将其用作找出上下文的键。这是可行的,但是单步执行Concurrency::CurrentScheduler::Id()
in 程序集让我有些畏缩,因为它执行多个虚拟函数调用和安全检查,这增加了很多开销,这有点问题,因为这种查找需要以极高的速度完成在某些情况下率。
那么 - 有没有更好的方法来实现这一点?我很想拥有一流的 TaskLocal/userdata 机制,它允许我将单个上下文指针与当前的 Scheduler/SchedulerGroup/Task 相关联,我可以用很少的开销进行检索。
每当 ConcRT 线程抓取新任务时调用的钩子将是我的理想选择,因为我可以检索 Scheduler/ScheduleGroup ID 并将其存储在本地线程中以最小化访问开销。唉,我看不到任何注册这样一个钩子的方法,而且似乎不可能为 PPL/代理实现自定义调度程序类(参见这篇文章)。