意外多线程结果

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (9)

我编写了几个Java类 - SingleThreadedCompute并且MultithreadedCompute- 以证明事实(或者我一直认为是事实!)如果您在单个核心机器上并行化以计算为中心(无I / O)任务,则不会获得加速。事实上,我的理解是并行化这些任务实际上会减慢速度,因为现在你必须处理上下文切换开销。好吧,我运行了类,并行版本出乎意料地运行得更快:单线程版本在我的机器上一直运行超过7秒,并且多线程版本在我的机器上一直运行超过6秒。谁能解释一下这是怎么回事?

如果有人想要查看或尝试自己,这是类。

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
  • 戴尔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毫秒

提问于
用户回答回答于

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

来自维基百科的超线程

超线程是超线程的进步。超线程(官方称为超线程技术或HTT)是一种英特尔专有技术,用于改进在PC微处理器上执行的计算并行化(一次执行多个任务)。启用了超线程的处理器被操作系统视为两个处理器而不是一个处理器。这意味着只有一个处理器在物理上存在但操作系统看到两个虚拟处理器,并在它们之间共享工作负载。

来自维基百科的piplining

在计算中,管道是一组串联连接的数据处理元件,因此一个元件的输出是下一个元件的输入。管道的元素通常以并行或时间切片的方式执行

热门问答

使用文档遇到问题,可以找谁处理?

请叫我雷锋!腾讯云文档有“文档反馈”的功能,直接在文档页面就可以反馈,反馈还有 礼品 ~ 云+社区:问答.png ... 展开详请

直播间IM消息可以下载到自己服务器备份吗?

人生的旅途辣鸡前端
推荐
目前仅私有群(Private)、公开群(Public)和聊天室(ChatRoom)具备消息漫游能力(默认7天)。核实下您那边的群组类型看是否支持https://cloud.tencent.com/document/product/269/1502#.E6.B6.88.E6.81....... 展开详请

webIM添加组员报错?

无聊至极互联网重度用户
推荐已采纳

付费超过组数限制,核实下是否超过限制

https://cloud.tencent.com/document/product/269/11673#.E5.8A.9F.E8.83.BD.E5.AF.B9.E6.AF.94

腾讯云容器加速地址是错的?

推荐已采纳

我刚才测试了一下,这个加速器地址可以用额,你这边是怎么测试出是关闭状态的啊?

加速器地址是不能直接用浏览器访问的,阿里云提供的直接访问也是空

Tencent iot-sdk-embedded-c在Windows下编译出错:无法解析外部符号?

无聊至极互联网重度用户
推荐已采纳

腾讯云IM调用 add_group_member提示该群不能邀请成员?

推荐已采纳
是什么类型的群?根据相应类型的邀请他人入群的控制项,对照文档看下是否允许邀请他人入群。 参考文档:https://cloud.tencent.com/document/product/269/1502#.E7.BE.A4.E6.88.90.E5.91.98.E6.93.8D.E4...... 展开详请

扫码关注云+社区

领取腾讯云代金券