当前位置: 首页 > 知识库问答 >
问题:

了解jvm中的循环性能

乜清野
2023-03-14

我在玩jmh,在关于循环的部分,他们说

您可能会注意到重复次数越多,被测量操作的“感知”成本就越低。到目前为止,我们每次添加都使用1/20 ns,远远超出了硬件的实际能力。发生这种情况是因为循环被大量展开/流水线化,并且要测量的操作是从循环中提升的。士气:不要过度使用循环,依靠JMH来获得正确的测量。

我自己也试过了

    @Benchmark
    @OperationsPerInvocation(1)
    public int measurewrong_1() {
        return reps(1);
    }      

    @Benchmark
    @OperationsPerInvocation(1000)
    public int measurewrong_1000() {
        return reps(1000);
    }      

并得到以下结果:

Benchmark                      Mode  Cnt  Score    Error  Units
MyBenchmark.measurewrong_1     avgt   15  2.425 ±  0.137  ns/op
MyBenchmark.measurewrong_1000  avgt   15  0.036 ±  0.001  ns/op

它确实显示了MyBenchmark。MeasureError\u 1000大大快于MyBenchmark。测量错误\u 1。但我无法真正理解JVM为提高性能所做的优化。

循环展开/流水线是什么意思?

共有3个答案

柴瀚昂
2023-03-14

循环流水线=软件流水线。

基本上,它是一种用于优化顺序循环迭代效率的技术,通过并行执行循环体中的一些指令。

当然,只有在满足某些条件时才能做到这一点,例如每次迭代不依赖于另一次迭代等。

来自insidehpc.com:

软件管道,实际上与硬件管道无关,是一种循环优化技术,用于使迭代中的语句相互独立。其目标是消除依赖关系,以便看似连续的指令可以并行执行。

在这里查看更多信息:

>

软件流水线-维基百科

郎曾笑
2023-03-14

循环展开是一种通过重复循环体来展平多个循环迭代的技术
例如,在给定示例中

    for (int i = 0; i < reps; i++) {
        s += (x + y);
    }

JIT编译器可以将其展开为

    for (int i = 0; i < reps - 15; i += 16) {
        s += (x + y);
        s += (x + y);
        // ... 16 times ...
        s += (x + y);
    }

然后可以进一步优化扩展环体,以

    for (int i = 0; i < reps - 15; i += 16) {
        s += 16 * (x + y);
    }

显然计算16*(x y)比计算(x y)快得多16倍。

诸葛文博
2023-03-14

循环展开使流水线成为可能。因此,可流水线CPU(例如RISC)可以并行执行展开的代码。

因此,如果您的CPU能够并行执行5个管道,您的循环将以以下方式展开:

// pseudo code
int pipelines = 5;
for(int i = 0; i < length; i += pipelines){
    s += (x + y);
    s += (x + y);
    s += (x + y);
    s += (x + y);
    s += (x + y);
}

IF=指令提取,ID=指令解码,EX=执行,MEM=内存访问,WB=寄存器写回

来自Oracle白皮书:

... 支持更快循环执行的标准编译器优化。循环展开增加了循环体的大小,同时减少了迭代次数。循环展开还可以提高其他优化的效率。

有关流水线的更多信息:经典RISC管道

 类似资料:
  • 问题内容: 我正在通过oracle认证的准Java SE7程序员实践考试(这本书),遇到一个问题,即使有解释,我也不明白答案。这是说明和代码: 它将打印3。循环主体执行两次,程序将打印3。 我不了解循环主体如何执行两次,也许我不了解什么意思。有人可以解释一下吗? 问题答案: 是 分配 其中B的逆分配给自身(真假之间有效地翻转) 在Java中,分配返回所分配的内容(因此可能) 因此将翻转b的值,然后

  • 问题内容: 我正在考虑,这是我想到的: 假设我们有这样的代码: 一个请求进入,并且JS引擎逐步开始执行上述代码。前两个呼叫是同步呼叫。但是当涉及到方法时,它将成为异步执行。但是JS立即从中返回并继续执行,这称为或。并且它继续在其他等等上工作。 执行结果如下: 交流数据库 因此,基本上第二个首先完成,其回调函数比第一个早执行,这是有道理的。 我们在这里谈论单线程应用程序。JS Engine会继续执行

  • 我试图找出为什么我的while循环没有在我希望的时候退出。基本上,我正在做一个简单的游戏,其中两个玩家玩单词,如果他们玩一个允许的单词,每轮都可以得分。一旦一个玩家打出一个以特定字符结尾的单词,该玩家就输掉了游戏。 我的方法是(在循环之前)设置一个值为false,然后使用while循环来保持游戏继续进行,直到玩家输入一个丢失的单词,此时循环应该立即退出,而不是进入玩家2(目前确实如此)。这基本上是

  • 问题内容: 到现在为止,我以前以:结束我的Tkiter程序,否则什么都不会出现!参见示例: 但是,当尝试该程序的下一步(使球随着时间移动)时,该书正在阅读,并说要执行以下操作。将绘图功能更改为: 并将以下代码添加到我的程序中: 但是我注意到,添加此代码块使之无用,因为即使没有它,所有内容也会显示出来!!! 此时,我应该提到我的书从未谈论过(也许是因为它使用了Python 3),但是由于我的程序无法

  • 本文向大家介绍深入了解java8的foreach循环,包括了深入了解java8的foreach循环的使用技巧和注意事项,需要的朋友参考一下 虽然java8出来很久了,但是之前用的一直也不多,最近正好学习了java8,推荐一本书还是不错的<写给大忙人看的javase8>。因为学习了Java8,所以只要能用到的地方都会去用,尤其是Java8的Stream,感觉用起来觉得很方便,因为点点点就出来了,而且

  • 问题内容: 当我的研究使我相信循环是PHP中最快的迭代构造…为了使它更清晰时,您认为以下哪个会更快? 示例一 示例二 我的逻辑是,在示例中的每次迭代中,在每次迭代中访问myLargeArray的长度比在示例二中访问简单的整数值要昂贵。那是对的吗? 问题答案: 第一种方法较慢,因为必须在循环的每次迭代中都调用该函数。该方法本身非常快,但是调用该函数仍然有一些开销。通过将其移动到循环之外,您正在执行所