并行检查列表中的每个项目与同一列表中的其他所有项目

时间:2019-01-29 16:20:43

标签: multithreading parallel-processing

我有数千个物品的清单。每个项目都有一个称为“地址范围”的属性。我有一个函数,通过确保其地址范围与列表中任何其他项目的地址范围都不重叠(每个项目恰好具有一个地址范围)来验证列表中项目的正确性。如果 N 是列表中的条目数,那么我基本上必须运行( N -1)* ( N / 2)地址范围重叠检查。换句话说,如果列表中的项目数增加了一倍,则重叠检查的数量将增加三倍。

一个月前,这样的列表只有几千个项目,并且整个操作将相对较快地完成,但是随着时间的流逝,项目的数量增加了,现在需要几分钟来运行所有的交叉检查。

我一直在尝试使交叉检查并行化,但是我还没有想到一种可行的方法。我的问题是,如果我想分发交叉检查以在例如8个线程上执行(以充分利用计算机上的CPU),则必须将可能的交叉检查组合分成8个独立的块。

举个例子,假设我们的列表中有5个项目:( A,B,C,D,E)。使用公式( N -1)*( N / 2),我们可以看到这需要( 5-1)*(5/2)= 10个交叉检查:

A vs B
A vs C
A vs D
A vs E
B vs C
B vs D
B vs E
C vs D
C vs E
D vs E

我能想到的在给定数量的线程上分布交叉检查组合的唯一方法是,首先创建所有交叉检查组合对的列表,然后将该列表分成大小均匀的块。从原理上讲这是可行的,但是即使对于列表中的仅20,000个项目,也已经包含(20,000-1)*(20,000 / 2)= 199,990,000个条目!

所以我的问题是,是否有一些超级复杂的算法可以让我将整个项目列表传递给每个线程,然后让每个线程自己找出要交叉检查的线程,这样就不会运行2线程会重复相同的交叉检查吗?

我正在用Perl编程,但是实际上问题是与任何特定的编程语言无关的。

编辑:嗯,我现在想知道我是否一直在以错误的方式去做这件事。如果可以按地址范围对项目进行排序,则可以浏览排序列表,然后检查是否有任何项目与其后继项目重叠。我会尝试一下,看看是否可以加快速度。

更新:哦,天哪,这确实有效!!! :D使用预排序列表,整个操作需要0.7秒的时间,可处理11,700个项目,而我以前的幼稚实现需要2到3分钟!

在usr的注释之后更新:如usr所述,仅检查每个项目的直接后继项是不够的。当我浏览排序列表时,我沿着另一个(最初是空的)列表拖动,在其中跟踪当前重叠中涉及的所有项目。每次发现一个项目与其后继项目重叠时,都会将后继项目添加到列表中(如果列表先前为空,则还会添加当前项目本身)。一旦某个项目与其后继项目不重叠,我就会在本地相互核对附加列表中的所有项目,然后清除该列表(如果我之后附加列表中仍然有任何项目,则执行相同的操作已经完成所有项目的清单了。

我的单元测试似乎证实了该算法的有效性;至少到目前为止,我已经提供了所有示例。

1 个答案:

答案 0 :(得分:0)

似乎可以创建N个线程,其中N =计算机上的内核数。这些线程中的每个线程都是相同的,并消耗队列中的项目,直到没有更多项目为止。每个项目都是线程应使用的比较对。由于一件物品只能消费一次,因此您不会获得重复的工作。

在生产者端,只需将每个有效的组合发送到队列(只是成对的项目)即可;线程是每个项目的工作内容。因此,无需将物品吐成大块。

如果每个线程都可以固定到一个内核,那就太好了,但是无论您运行的是哪种操作系统,在调度方面都可能做得很好,而您不必担心。