我正在尝试学习一些基本的基准测试。我的 Java 程序中有一个循环,例如,
float a=6.5f;
int b=3;
for(long j=0; j<999999999; j++){
var = a*b+(a/b);
}//end of for
我的处理器需要大约 0.431635 秒来处理这个。如何根据 Flops(每秒浮点操作数)和 Iops(每秒整数操作数)计算处理器速度?你能提供一些步骤的解释吗?
我正在尝试学习一些基本的基准测试。我的 Java 程序中有一个循环,例如,
float a=6.5f;
int b=3;
for(long j=0; j<999999999; j++){
var = a*b+(a/b);
}//end of for
我的处理器需要大约 0.431635 秒来处理这个。如何根据 Flops(每秒浮点操作数)和 Iops(每秒整数操作数)计算处理器速度?你能提供一些步骤的解释吗?
您有一个包含 999999999 次迭代的循环:为简单起见,我们将其称为 1e9(十亿)。在涉及两者的计算中,整数将被提升为浮点数,因此循环包含 3 个浮点运算:一个 mult、一个 add 和一个 div,所以有 3e9。这需要 0.432 秒,所以你显然得到了大约 6.94 GFLOP/s (3e9/0.432)。同样,您在j++
每次循环迭代中执行 1 个整数 op ( ),因此您将获得 1e9/0.432 或大约 2.32 GIOP/s。
然而,计算a*b+(a/b)
是循环不变的,所以如果这没有得到优化,那将是非常令人惊讶的。我对 Java 了解不多,但是任何 C 编译器都会在编译时评估它,删除a
andb
变量和循环,并(有效地)用var=21.667;
. javac
这是一个非常基本的优化,所以如果不这样做我会感到惊讶。
我不知道 Java 的底层发生了什么,但我怀疑获得 7 GFLOPs。现代英特尔 CPU(我假设这就是您所拥有的)原则上能够在每个时钟周期使用正确的指令组合(每个周期一个加法和一个乘法运算)进行两个矢量算术运算,因此对于 3 GHz 4 -core CPU,在理想条件下甚至可以得到 3e9*4*8 = 96 个单精度 GFLOPs。各种mul
和add
指令的吞吐量倒数为 1 个周期,但div
需要十倍以上的时间,所以一旦涉及除法,我会非常怀疑获得超过 CLK/12 FLOPs(单核上的标量除法):如果编译器足够聪明,可以矢量化和/或并行化要获得更多的代码,它必须这样做,它肯定足够聪明,可以优化整个循环。
总之,我怀疑循环正在被完全优化掉,你看到的 0.432 秒只是开销。您没有给出任何指示您如何为上述循环计时,所以我不能确定。您可以通过将 ~1e9 循环迭代替换为 1e10 来亲自检查这一点。如果它不需要大约 10 倍的时间,那么你就没有按照你认为的时间来计时。
关于基准测试和性能分析还有很多话要说,但我会就此搁置。
我知道这已经很晚了,但我希望它对某人有所帮助。
埃米特。