简体   繁体   English

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

[英]Multithreading slows down with more cores

Im trying to implement Eratosthenes prime sieve with multithreading. 我试图用多线程实现Eratosthenes prime筛子。 The threads are taken care of by a treadpool 线程由踏板处理

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

And the sieve it self is implemented like this 它自己的筛子是这样实现的

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

with the run method looking like this 使用run方法看起来像这样

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

Now, what i dont understand is why, when the corePoolSize is lower (other parameters stay the same), the program runs faster. 现在,我不明白为什么,当corePoolSize较低时(其他参数保持不变),程序运行得更快。 (2 cores 2.5 Milliseconds; 7 - 3.3; etc.). (2核2.5毫秒; 7 - 3.3;等)。 I think i might be making some rookie mistake, but i dont understand why this is happening? 我想我可能会犯一些菜鸟错误,但我不明白为什么会发生这种情况?

EDIT: Full class looks like this (have to use a single class for the cluster, hence everything is in Main: 编辑:完整类看起来像这样(必须为集群使用单个类,因此一切都在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.");

    }

}

It depends a lot on how many cores you have. 这取决于你拥有多少核心。 If you have 2 cores and you want to execute on 7 threads will just make the things slower because of the thread context switching. 如果你有2个内核,并且你想在7个线程上执行,那么由于线程上下文切换会使事情变慢。 This is called Amdahl's law. 这被称为阿姆达尔定律。

Also is worth mentioning that the first 2 parameters for the executor constructor are corePoolSize and maximumPoolSize java doc corePoolSize means the number of threads to keep in the pool, even if they are idl while maximumPoolSize is the maximum number of threads to allow in the pool 还值得一提的是,执行程序构造函数的前2个参数是corePoolSize和maximumPoolSize java doc corePoolSize表示要保留在池中的线​​程数,即使它们是idl而maximumPoolSizemaximumPoolSize的最大线程数

Anyways the main reason is that the only thing you are measuring is how much it takes for the executor to shut down. 无论如何,主要原因是你唯一测量的是执行者关闭所需的时间。 You initialize the array with false: list[i]=new AtomicBoolean(false); 用false初始化数组: list[i]=new AtomicBoolean(false); Then the only situation you create a task for the thread pool is when you find a true element if (list[i]){ . 那么你为线程池创建任务的唯一情况是当你找到一个真正的元素if (list[i]){ since there is no true element this will never happen so no task will be scheduled/executed. 由于没有真正的元素,这将永远不会发生,因此不会安排/执行任务。

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

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