java-Fork / Join:最佳线程数
作者:互联网
任务定义:我需要映射一个很大的数组.例如,让我们成为afindMax()函数.因此,任务是尽可能快地执行此操作(这意味着并行执行).
硬件:我有8个核心,每个核心都有2个超线程
public static void main(String... args) {
int maxThreadAmount = Runtime.getRuntime().availableProcessors(); // GET 8
}
解决方案1:只是为了将任务运行到N个线程中.其中N应该是某个最佳数.
问题#1:是下一个权利:int OptimalThreadAmount = maxThreadAmount-1吗?
解决方案2:我想通过Fork / Join框架解决该问题.如果输入太大,则每个任务会分成两个并行的子任务.所以我会得到类似
Find Max
[array] <---- +1 pending thread
/ \
/ \
Find Max Find Max
[1/2 array] [1/2 array] <-------- +2 pending threads
/ \ / \
/ \ .. ..
Find Max Find Max
[1/4 array] [1/4 array] <-------- +4 four pending threads
/ \ / \
/ \ .. ..
Find Max Find Max
[1/8 array] [1/8 array] <----------- +8 active threads
问题2:考虑到使用Fork / Join算法,我们将获得一堆待处理线程,最佳线程数是多少?
解决方法:
最佳线程数应在计算机具有的内核数附近.但是,请记住,将工作负载分为两个子任务时,应计算一个任务,而应将另一个分支.这意味着拆分时仅创建一个额外的线程.
大多数分叉/联接算法都伴随有顺序截止.当您达到特定条件时(例如,用于确定大小为1000的最大值的数组),您将切换到顺序算法(即,逐个检查元素).因此,如果我猜测最佳情况来计算您的问题,我会说,目前您已经分裂了14次,产生了16个线程,然后切换到顺序算法.这意味着每个内核都有一个正在运行的线程,因此将保持繁忙状态. (此猜测假设您的内核具有超线程之类的功能,如果没有,我会说8个线程).
另外,不建议对您给出的方程式进行修正(int OptimalThreadAmount = maxThreadAmount-1),因为这意味着您假设计算机不做任何其他事情,并且可以使用所有线程.
我的猜测是,当使用顺序中断时,您的最佳性能将约为16个线程(当没有其他进程在使用您的计算机时).您可以自己进行测试,这始终是最好的方法.您要研究的问题是,当您开始产生大量线程时,每个线程的开销将变得显而易见.
附言:使用fork / join的优点是,您的代码将能够根据计算机具有的内核数进行很好的扩展.更多的内核意味着更多的线程将并行运行.这意味着您的线程调度程序可以将更多线程用于工作.
编辑
那么对于给定数量的内核,我应该使用的最佳截止频率是多少?
好吧,我的猜测是您将实现一个fork / join算法.您有一个连续的截止时间(即,一旦我的输入数组的大小为x,就停止分叉并加入).
当您知道必须在哪个系统上运行算法时,便可以运行基准测试.
对于从x到y的连续截止,您可以运行代码.每次迭代都测量应用算法需要多长时间.这样,您将看到最适合您的配置.
再说一次,如果您想要一种快速而肮脏的方法,可以执行以下操作:
具有p核的机器,输入数组的大小为s:
Sequential cutoff = s/8
但是,如前所述,我强烈建议不要这样做.
标签:performance,multithreading,concurrency,fork-join,java 来源: https://codeday.me/bug/20191029/1960019.html