我编写了两个Java类SingleThreadedComputeMultithreadedCompute来演示以下事实(或我一直认为是事实!),如果您在单台核心计算机上并行执行以计算为中心的任务(无I/O),您不会没有得到加速。实际上,我的理解是并行执行此类任务实际上会使速度变慢,因为现在您必须处理上下文切换开销。好吧,我运行了类,并行版本出乎意料地运行得更快:单线程版本在我的计算机上始终运行仅超过7秒,而多线程版本在我的计算机上始终运行仅超过6秒。谁能解释这是怎么可能的?

如果有人要亲自看或尝试一下,这里是一些类(class)。

public final class SingleThreadedCompute {
    private static final long _1B = 1000000000L; // one billion

    public static void main(String[] args) {
        long startMs = System.currentTimeMillis();

        long total = 0;
        for (long i = 0; i < _1B; i++) { total += i; }
        System.out.println("total=" + total);

        long elapsedMs = System.currentTimeMillis() - startMs;
        System.out.println("Elapsed time: " + elapsedMs + " ms");
    }
}

这是多线程版本:
public final class MultithreadedCompute {
    private static final long _1B = 1000000000L; // one billion
    private static final long _100M = _1B / 10L;

    public static void main(String[] args) {
        long startMs = System.currentTimeMillis();

        System.out.println("Creating workers");
        Worker[] workers = new Worker[10];
        for (int i = 0; i < 10; i++) {
            workers[i] = new Worker(i * _100M, (i+1) * _100M);
        }

        System.out.println("Starting workers");
        for (int i = 0; i < 10; i++) { workers[i].start(); }

        for (int i = 0; i < 10; i++) {
            try {
                workers[i].join();
                System.out.println("Joined with thread " + i);
            } catch (InterruptedException e) { /* can't happen */ }
        }

        System.out.println("Summing worker totals");
        long total = 0;
        for (int i = 0; i < 10; i++) { total += workers[i].getTotal(); }
        System.out.println("total=" + total);

        long elapsedMs = System.currentTimeMillis() - startMs;
        System.out.println("Elapsed time: " + elapsedMs + " ms");
    }

    private static class Worker extends Thread {
        private long start, end;
        private long total;

        public Worker(long start, long end) {
            this.start = start;
            this.end = end;
        }

        public void run() {
            System.out.println("Computing sum " + start + " + ... + (" + end + " - 1)");
            for (long i = start; i < end; i++) { total += i; }
        }

        public long getTotal() { return total; }
    }
}

这是运行单线程版本的输出:
total=499999999500000000
Elapsed time: 7031 ms

这是运行多线程版本的输出:
Creating workers
Starting workers
Computing sum 0 + ... + (100000000 - 1)
Computing sum 100000000 + ... + (200000000 - 1)
Computing sum 200000000 + ... + (300000000 - 1)
Computing sum 300000000 + ... + (400000000 - 1)
Computing sum 400000000 + ... + (500000000 - 1)
Computing sum 500000000 + ... + (600000000 - 1)
Computing sum 600000000 + ... + (700000000 - 1)
Computing sum 700000000 + ... + (800000000 - 1)
Computing sum 800000000 + ... + (900000000 - 1)
Computing sum 900000000 + ... + (1000000000 - 1)
Joined with thread 0
Joined with thread 1
Joined with thread 2
Joined with thread 3
Joined with thread 4
Joined with thread 5
Joined with thread 6
Joined with thread 7
Joined with thread 8
Joined with thread 9
Summing worker totals
total=499999999500000000
Elapsed time: 6172 ms

编辑:有关环境的信息:
  • Microsoft Windows XP Professional版本2002 SP3
  • Dell Precision 670
  • Intel Xeon CPU 2.80GHz,1 MB L2缓存

  • 除了通过陈述上面的规范并注意到我在购买机器时(2005年8月)时指出的那样,不知道如何证明它是单核计算机,所以单核是标准的,并且我没有升级到多核(如果是这样的话)。一个选项...我不记得了)。如果Windows中有某个地方,我可以检查系统属性(显示上面的信息)以外的地方,让我知道,我将进行检查。

    这是五个连续的ST和MT运行:

    五次单次运行:

    总计= 499999999500000000
    耗时:7000毫秒

    总计= 499999999500000000
    耗用时间:7031毫秒

    总计= 499999999500000000
    耗用时间:6922毫秒

    总计= 499999999500000000
    耗用时间:6968毫秒

    总计= 499999999500000000
    耗用时间:6938毫秒

    五种多线程运行:

    总计= 499999999500000000
    耗用时间:6047毫秒

    总计= 499999999500000000
    耗用时间:6141毫秒

    总计= 499999999500000000
    耗用时间:6063毫秒

    总计= 499999999500000000
    耗用时间:6282毫秒

    总计= 499999999500000000
    耗用时间:6125毫秒

    最佳答案

    这可能是由于超线程和/或流水线造成的。

    来自维基百科on hyper-threading:



    来自维基百科on piplining:

    关于java - 意外的多线程结果,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/519099/

    10-11 10:38