使用多个线程搜索数组,同时不做任何不必要的额外工作

Posted

技术标签:

【中文标题】使用多个线程搜索数组,同时不做任何不必要的额外工作【英文标题】:Search through array with multiple threads while not doing any more extra work than necessary 【发布时间】:2018-10-15 15:32:59 【问题描述】:

假设您有一个长度为 n 的 未排序数组,您想要搜索该数组以找到特定元素(让该数组的元素是唯一的)。由于在最坏的情况下您必须在整个数组中搜索元素,因此运行时间将是 O(n)。但是,由于现在大多数 CPU 都支持多核(使用超线程),因此您可以让多个线程在数组中搜索以加快速度。因此,使用 m 个内核,您将拥有 2m(独立)线程供您使用。如果您只将数组的一部分委托给每个线程,即让 2m 个线程中的每一个线程 n/2m 个元素来处理,那将是最佳的。但是,当 2m 个线程中的一个找到该元素时,其他线程将需要停止(以保留系统资源),因为所有元素都是唯一的,其他线程将永远找不到该元素。

所以我的问题是: 您将如何搜索具有 2m 线程的唯一元素的大型未排序数组,同时最大限度地减少线程完成的工作和运行时间?您需要什么同步数据结构?找到元素后如何停止其他2m-1个线程?

【问题讨论】:

【参考方案1】:

可能最简单的方法是使用 atomic-boolean(C++ 语言中的 std::atomic<bool>),并在退出之前让找到该布尔值的线程设置为 true。

除此之外,让每个线程将其数组的部分划分为子部分,以便它可以执行紧密循环以查找每个子部分中的数字,然后检查 atomic-boolean,然后重复直到它用完要检查的子部分。 (使用子部分而不是在一个大的 for 循环的每次迭代后检查原子布尔值的原因是,由于缓存一致性问题,即使检查原子布尔值也会相当昂贵,因此最好摊销每个atomic-boolean-check 对大量迭代进行检查并权衡一些额外/浪费的工作以换取更好的并行性)

制作每个子部分的理想尺寸是您需要凭经验得出的,通过尝试不同的尺寸,直到找到性能最佳的尺寸。

【讨论】:

以上是关于使用多个线程搜索数组,同时不做任何不必要的额外工作的主要内容,如果未能解决你的问题,请参考以下文章

Java 并发 – 线程安全?

第六章 - 线程安全

同时重启多个锁定线程

Java虚拟机—线程安全和锁优化

并行搜索

C/C++ 并行搜索 算法