【问题标题】:Hashing on multiple keys : for task execution In Multi threaded environment散列多个键:用于多线程环境中的任务执行
【发布时间】:2014-11-19 15:03:00
【问题描述】:

我有某些对象需要执行某些任务。在所有对象上,所有任务都需要执行。我想使用多个线程说 N 个并行线程

假设我有像 A、B、C 这样的对象标识符(对象可以在 100 K 范围内;键可以是长字符串或字符串) 任务可以 T1,T2,T3,TN - (任务数量最多 20 个)

任务执行的条件—— 即使对于同一个对象,任务也可以并行执行。 但是对于同一个对象,对于一个给定的任务,它应该是串行执行的。 例如,假设我有 执行任务的对象是 A,B,A 和任务是t1,t2

所以 T1(A), T2(A) 或 T1(A) , T2(B) 是可能的,但 T1(A) 和 T1(A) 不应该被允许

我如何确保满足我的条件。我知道我必须使用某种散列。 我读过关于散列的信息,所以我的散列函数可以是 -

返回 ObjectIdentifier.getHashCode() + TaskIdentifier.getHashCode() 或其他可以是 - a^3 + b^2 (其中 a 和 b 分别是对象标识符和任务标识符的哈希) 什么是最好的策略,任何建议

我的任务不涉及任何 IO,到目前为止,我为每个任务使用一个线程。 所以我目前的设计还可以,或者我应该尝试根据处理器数量来优化它。 (有固定的线程数)

【问题讨论】:

  • 感谢您的回答,您好,我的 ListOfObjects 是我从外部程序接收的一系列消息(通过阻塞集合)。在完成 n 条消息或接收条件后,我必须停止处理消息,处理该条件,然后恢复处理(继续阻塞收集循环)。我无法理解如何使用来自阻塞收集的消息来实现上述目标

标签: c# multithreading parallel-processing hashcode


【解决方案1】:

我必须说我真的很喜欢 Rufus L 的回答。你必须对你并行化的事情很聪明,而不是用过多的线程同步和内存密集型结构过度阻碍你的实现——这些事情会削弱并行化的好处。鉴于项目池的大尺寸和工作的 CPU 绑定性质,具有顺序内部循环的Parallel.ForEach 应该提供非常合理的性能,同时保持实现非常简单。这是一场胜利。

话虽如此,我对 Rufus 的回答有一个非常微不足道的基于 LINQ 的调整,它解决了您的其他要求(对于同一个对象,对于给定的任务,它应该按顺序执行)。如果满足以下假设,则该解决方案有效:

  • 任务的执行顺序并不重要。
  • 要执行的工作(task x object 的所有组合)是预先知道的,不能更改。
  • (很抱歉说的很明显)您要并行化的工作可以并行化 - 即没有共享资源/副作用是完全隔离的。

考虑到这些假设,请考虑以下事项:

// Cartesian product of the two sets (*objects* and *tasks*).
var workItems = objects.SelectMany(
    o => tasks.Select(t => new { Object = o, Task = t })
);

// Group *work items* and materialise *work item groups*.
var workItemGroups = workItems
    .GroupBy(i => i, (key, items) => items.ToArray())
    .ToArray();

Parallel.ForEach(workItemGroups, workItemGroup =>
{
    // Execute non-unique *task* x *object*
    // combinations sequentially.
    foreach (var workItem in workItemGroup)
    {
        workItem.Task.Execute(workItem.Object);
    }
});

请注意,我并没有限制Parallel.ForEach 中的并行度。由于所有工作都受 CPU 限制,因此它会自行计算出最佳线程数。

【讨论】:

    【解决方案2】:

    您可以在其中一个列表上执行Parallel.ForEach,在另一个列表上执行常规 foreach,例如:

    Parallel.ForEach (myListOfObjects, currentObject =>
    {
        foreach(var task in myListOfTasks)
        {
            task.DoSomething(currentObject);
        }
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-07
      • 1970-01-01
      • 2012-06-25
      • 2016-02-21
      • 1970-01-01
      相关资源
      最近更新 更多