6

我正在通过使其更加异步来改进应用程序(Win64、C++)。我正在使用并发运行时,到目前为止它对我来说效果很好。

该应用程序基本上执行许多“作业”转换数据。为了跟踪每个作业的功能,某些子系统配备了代码来跟踪作业执行的某些操作。以前,这将使用表示当前正在执行的作业的单个全局变量来注册跟踪信息,而无需将上下文信息一直传递到调用链中。每个作业也可以轮流使用 ConcRT 来并行化作业本身。这一切都很好。

不过,现在我正在重构应用程序,以便我们可以并行执行顶级作业。每个作业都作为 ConcRT 任务执行,这适用于除需要跟踪的作业之外的所有作业。

我基本上需要的是一种将一些上下文信息与任务相关联的方法,并将该流程流向由该任务产生的任何其他任务。基本上,我需要“任务本地”变量。

使用 ConcRT,我们不能简单地使用线程局部变量来存储上下文信息,因为该作业可能会使用 ConcRT 生成其他作业,并且这些作业将在任意数量的线程上执行。

我目前的方法包括在启动时创建许多调度程序实例,并在专用于该作业的调度程序中生成每个作业。然后我可以使用该Concurrency::CurrentScheduler::Id()函数检索一个整数 ID,我可以将其用作找出上下文的键。这是可行的,但是单步执行Concurrency::CurrentScheduler::Id()in 程序集让我有些畏缩,因为它执行多个虚拟函数调用和安全检查,这增加了很多开销,这有点问题,因为这种查找需要以极高的速度完成在某些情况下率。

那么 - 有没有更好的方法来实现这一点?我很想拥有一流的 TaskLocal/userdata 机制,它允许我将单个上下文指针与当前的 Scheduler/SchedulerGroup/Task 相关联,我可以用很少的开销进行检索。

每当 ConcRT 线程抓取新任务时调用的钩子将是我的理想选择,因为我可以检索 Scheduler/ScheduleGroup ID 并将其存储在本地线程中以最小化访问开销。唉,我看不到任何注册这样一个钩子的方法,而且似乎不可能为 PPL/代理实现自定义调度程序类(参见这篇文章)。

4

1 回答 1

0

是否有某种原因您不能将某种上下文对象传递给这些任务,从而为它们提供更新状态的接口?因为从我的立场来看,听起来你对单例(又名全局变量)有一个非常糟糕的问题,应该通过依赖注入来解决这个问题。

如果依赖注入不是一种选择,那么还有另一种处理单例的策略。该策略基本上允许 Singleton 成为“堆栈”。您可以将一个新值“推送”到 Singleton,然后访问它的每个人都会获得这个新值。然后您可以“弹出”该值并恢复推送之前的值。这不必直接用实际的堆栈建模,这就是为什么我将“push”、“pop”和“stack”这三个词放在引号中。

您可以通过使用该变量的父线程版本的值(不是整个值堆栈,只是顶部值)初始化的线程本地 Singleton 来调整此模型以适应您的情况。然后,如果该线程及其子线程需要新的上下文,您可以将新值推送到线程本地 Singleton。

于 2012-10-17T20:00:09.337 回答