繁体   English   中英

多线程随着更多内核而变慢

[英]Multithreading slows down with more cores

我试图用多线程实现Eratosthenes prime筛子。 线程由踏板处理

ThreadPoolExecutor executor = 
    new ThreadPoolExecutor(
        6,   // cores
        10,  // threads
        1000,
        TimeUnit.MILLISECONDS, 
        new ArrayBlockingQueue<Runnable>(n)
    );

它自己的筛子是这样实现的

for (int i=2; i<Math.sqrt(n); i++ ){
    if (list[i].get()) { // boolean list initialized earlier
        executor.execute(new Calc(i,n));
    }
}

使用run方法看起来像这样

public void run(){
    for (int j=start*2;j<n;j=j+start){ 
        list[j].set(false); 
    }   
}

现在,我不明白为什么,当corePoolSize较低时(其他参数保持不变),程序运行得更快。 (2核2.5毫秒; 7 - 3.3;等)。 我想我可能会犯一些菜鸟错误,但我不明白为什么会发生这种情况?

编辑:完整类看起来像这样(必须为集群使用单个类,因此一切都在Main中:

int start;
int n;
Main(int start,int n){
    this.start=start;
    this.n=n;
}
public void run(){
            for (int j=start*2;j<n;j=j+start){
                list[j].set(true);
            }


        }


private static list myBoolean[];

   public static void main(String[] args) {
    int  n = 20000;     
    list= new AtomicBoolean[n+1];


for (int i=2; i<n; i++ ){
            list[i]=new AtomicBoolean(false);
       }
      ThreadPoolExecutor executor = 
                new ThreadPoolExecutor(
                        7,
                    10,
                    1000,
                    TimeUnit.MILLISECONDS, 
                    new ArrayBlockingQueue<Runnable>(n));

    long startedTime = System.nanoTime();
    for (int i=2; i<Math.sqrt(n); i++ ){
        if (list[i]){
            executor.execute(new Main(i,n));
        }
    }   

    executor.shutdown();
    try {
        executor.awaitTermination(60, TimeUnit.MINUTES);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }   
    System.out.println("Work time "+(float)(System.nanoTime()-startedTime)/1000000+" s.");

    }

}

这取决于你拥有多少核心。 如果你有2个内核,并且你想在7个线程上执行,那么由于线程上下文切换会使事情变慢。 这被称为阿姆达尔定律。

还值得一提的是,执行程序构造函数的前2个参数是corePoolSize和maximumPoolSize java doc corePoolSize表示要保留在池中的线​​程数,即使它们是idl而maximumPoolSizemaximumPoolSize的最大线程数

无论如何,主要原因是你唯一测量的是执行者关闭所需的时间。 用false初始化数组: list[i]=new AtomicBoolean(false); 那么你为线程池创建任务的唯一情况是当你找到一个真正的元素if (list[i]){ 由于没有真正的元素,这将永远不会发生,因此不会安排/执行任务。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM