当您将算法/函数/其他内容拆分为单独的线程运行时,假设我启动了 8 个线程,您不知道每个线程将在我的 8 个内核中的一个内核上运行,因为调度程序的工作是决定将哪些线程分配给哪些内核。不过,如果我有 8 个内核,并且我确实将作业拆分为 8 个线程,我几乎可以预料到会发生这种情况,我的 8 个内核中的每一个(大约)将承担八分之一的工作负载。对于具有 P 内核和 E 内核(性能和效率内核)的英特尔处理器,P 内核的时钟频率可能为 5.4Ghz,而 E 内核的时钟频率可能为 4.2Ghz。这种具有两种不同类型处理器的处理器是否会使多线程编程更加不可预测或更不受欢迎?两层系统在其他设备(如智能手机和 Apple CPU)中很常见,同样的问题也适用。作为一名程序员,你该如何解释这样一个事实:当你在不同的线程上运行某些东西时,比如你生成一个新线程,或者另一个线程在线程池中等待作业,它可能运行在性能核心或效率核心上?你有选择吗?
如果您将工作量划分为大小相等的部分,那么 P 核心将首先完成。但是,如果您将其划分为较小的部分,并让线程在完成第一个部分时抓取另一个部分,例如 OpenMP schedule=dynamic 而不是 static,那么您可以让所有核心保持忙碌状态,直到所有工作完成。
或者,如果有许多可并行化的任务需要完成,并且后面的任务可以在前面的一些线程仍在完成时启动,这样就可以轻松地将工作发送到线程池。
如果存在任何其他负载,那么将 8 核 CPU 的工作划分为 8 个大小相等的部分即使在同构 CPU 上也可能是不好的:如果某些线程暂时被取消调度,它们将不会像一直运行的线程那样早完成。(特别是如果总时间与调度粒度在同一尺度上,例如,对于 HZ=100 的 Linux,总时间是 10 毫秒。)
因此,已经有理由将工作划分为中等大小的块以供线程使用,特别是如果您使用像 OpenMP 这样的复杂线程池系统,它可以为您完成这项工作而无需编写大量额外的代码。