为什么单线程操作g花费的时间是无线程操作的3倍?

问题描述 投票:0回答:1

我正在用Java测试并发性,我的目标是确定拥有多个线程是否实际上是有益的,但是,我得到的结果并没有加总。我正在尝试优化阶乘函数,对于此特定测试,我正在使用1e9!我想要模1e9 + 7的结果,以免溢出。首先,我根据number_of_threads划分数字,并分别为每个线程分配其工作。然后,我通常会这样做并比较我得到的时间。看来,当number_of_threads = 4时,与没有线程的版本相比,我得到的结果更好,这是有道理的,因为我的CPU有4个内核。不出所料,大于4的任何线程数的时间都比仅4的慢。但是,当线程数少于4时,结果变得很大,例如,对于1个线程,我希望它的持续时间与执行相同它没有线程+开销。没有线程,我只有1个线程的时间是6.2秒和19.3,这对它来说仅仅是开销而已。

为了测试原因,我在run方法上添加了一个计数器,有时似乎只执行一次for的内部周期要花费一毫秒多的时间,因此不应该这样做,因为它只是两个操作加上计时器。

public class Calc implements Runnable{
    long min, max, mod, res;
    Res r;
    public Calc(long min, long max, long mod, Res r) {
        this.min = min;
        this.max = max;
        this.mod = mod;
        res = 1;
        this.r = r;
    }
    public void run() {
        for(long i = min; i <= max; i++) {
            res *= i;
            res %= mod;
        }
        r.addup(res);
    }
}

public class Res{
    long result;
    long mod;
    public Res(long mod) {
        result = 1;
        this.mod = mod;
    }
    public synchronized void addup(long add) {
        result *= add;
        result %= mod;
    }
    public long getResult() {
        return result;
    }
}

public class Main{
    public static void main(String args[]) {
        long startTime = System.nanoTime();
        final long factorial = 1000000000L;
        final long modulo = 1000000007L;
        Res res = new Res(modulo);
        int number_of_threads = 1;
        Thread[] c = new Thread[number_of_threads];
        long min = 1, max = factorial/(long)number_of_threads;
        long cant = max;
        for(int i = 0; i < number_of_threads; i++) {
            if((long)i < (factorial % number_of_threads))max++;
            c[i] = new Thread(new Calc(min, max, modulo, res));
            c[i].start();
            min = max +1;
            max += cant;
        }
        for(int i = 0; i < number_of_threads; i++) {
            try {
                c[i].join();
            }catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println(res.getResult());
        long endTime   = System.nanoTime();
        long totalTime = endTime - startTime;
        System.out.println((double)totalTime/1000000000L);
    }
}

[number_of_threads = 1时,我得到19.3秒。当number_of_threads = 2时,我得到10.1秒。当number_of_threads = 3时,我得到7.1秒。当number_of_threads = 4时,我得到5.4秒。当没有线程时,我得到6.2秒(我用相同的方法计算出这个时间)

只有1个线程和没有线程之间应该没有太大的区别,对于2和3个线程,它应该比没有线程快。为什么会这样,有什么办法可以解决?谢谢。

编辑:添加无线程版本

public class Main{
    public static void main(String args[]) {
        long startTime = System.nanoTime();
        final long factorial = 1000000000L;
        final long modulo = 1000000007L;

        long res = 1;
        for(long i = 1; i <= factorial; i++) {
            res *= i;
            res %= modulo;
        }
        System.out.println(res);
        long endTime   = System.nanoTime();
        long totalTime = endTime - startTime;
        System.out.println((double)totalTime/1000000000L);
    }

}

我正在用Java测试并发性,我的目标是确定拥有多个线程是否实际上是有益的,但是,我得到的结果并没有加总。我正在尝试优化阶乘...

java multithreading time cpu
1个回答
0
投票

这是因为您的“无线程”(仅主线程)版本使用所有易于优化的编译时常量。

© www.soinside.com 2019 - 2024. All rights reserved.