对多个键进行哈希:用于在多线程环境中执行任务

本文关键字:用于 多线程 环境 执行任务 哈希 | 更新日期: 2023-09-27 18:24:35

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

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

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

因此,T1(A)、T2(A)或T1(A

我如何才能确保我的条件得到满足。我知道我必须使用某种散列。我读过关于哈希的文章,所以我的哈希函数可以是-

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

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

对多个键进行哈希:用于在多线程环境中执行任务

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

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

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

话虽如此,我对Rufus的答案进行了一个非常琐碎的基于LINQ的调整,它解决了您的另一个需求(对于同一对象,对于给定的任务,它应该在系列中执行)。如果以下假设成立,则解决方案有效:

  • 执行任务的顺序并不重要
  • 要执行的工作(任务x对象的所有组合)是事先已知的,不能更改
  • (很抱歉说了显而易见的话)你想并行的工作可以并行,即没有共享资源/副作用是完全孤立的

考虑到这些假设,请考虑以下内容:

// 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绑定的,因此它将自己计算出最佳数量的线程。