【问题标题】:Benchmarking the CPU calculation power对 CPU 计算能力进行基准测试
【发布时间】:2016-12-25 07:25:15
【问题描述】:

我正在尝试用一个简单的函数来衡量 CPU 计算能力,而不是在我的项目中添加包含数千行和一些 MB 的庞大框架。

我开发了这个示例代码。这是一项完成 100 次艰巨任务的工具。这个巨大的任务(benchmark() 函数)包含一段时间,它将在 100 毫秒内执行数学复杂计算并增加一个计数器。每 100 毫秒,它会在日志中打印 benchmark() 函数完成复杂数学计算的次数。

好的,所以,我在屏幕上打印了 100 次计算。

我第一次执行基准测试时,我得到了正确的结果,对于 100 次基准测试迭代中的每一次,或多或少相同的日志结果:

08-18 13:09:52.806 26543-27748/com.mytestapp D/XXXX: Iteration: 0 Result: 118200
08-18 13:09:52.906 26543-27748/com.mytestapp D/XXXX: Iteration: 1 Result: 171580
08-18 13:09:53.006 26543-27748/com.mytestapp D/XXXX: Iteration: 2 Result: 170654
08-18 13:09:53.106 26543-27748/com.mytestapp D/XXXX: Iteration: 3 Result: 168676
08-18 13:09:53.206 26543-27748/com.mytestapp D/XXXX: Iteration: 4 Result: 168372
08-18 13:09:53.306 26543-27748/com.mytestapp D/XXXX: Iteration: 5 Result: 165558
08-18 13:09:53.406 26543-27748/com.mytestapp D/XXXX: Iteration: 6 Result: 171368
08-18 13:09:53.506 26543-27748/com.mytestapp D/XXXX: Iteration: 7 Result: 171680
08-18 13:09:53.606 26543-27748/com.mytestapp D/XXXX: Iteration: 8 Result: 171516
08-18 13:09:53.706 26543-27748/com.mytestapp D/XXXX: Iteration: 9 Result: 171598

但在一些处决之后,数量开始减少,我不明白为什么:

08-18 13:10:20.850 26543-28161/com.mytestapp D/XXXX: Iteration: 1 Result: 94320
08-18 13:10:20.951 26543-28161/com.mytestapp D/XXXX: Iteration: 2 Result: 90364
08-18 13:10:21.051 26543-28161/com.mytestapp D/XXXX: Iteration: 3 Result: 94240
08-18 13:10:21.152 26543-28161/com.mytestapp D/XXXX: Iteration: 4 Result: 93676
08-18 13:10:21.252 26543-28161/com.mytestapp D/XXXX: Iteration: 5 Result: 91554
08-18 13:10:21.352 26543-28161/com.mytestapp D/XXXX: Iteration: 6 Result: 94358
08-18 13:10:21.452 26543-28161/com.mytestapp D/XXXX: Iteration: 7 Result: 90954
08-18 13:10:21.552 26543-28161/com.mytestapp D/XXXX: Iteration: 8 Result: 94874
08-18 13:10:21.652 26543-28161/com.mytestapp D/XXXX: Iteration: 9 Result: 94464

如果我等待几分钟再试一次,结果会再次增加到正常值。

为什么会有这种行为?如何避免它并始终获得正确的基准测试结果?

这是我的示例代码:

public void benchmarkIterator(){
    int result = 0;
    int iterations = 100;
    for (int i=0; i<iterations; i++){
       result = benchmark();
       Log.d("XXXX", "Iteration: "+i+" Result: "+result);
    }
}

....

     public int benchmark(){
        long startTime = System.currentTimeMillis();
        int count=0;
        double aux=0;
        while((System.currentTimeMillis()-startTime)<100){
            count++;
            double d = 7777777777d;
            aux = 0;
            aux=aux+(int)(aux+Math.sin(d)*Math.cos(d));
        }
        return count;
    }

【问题讨论】:

  • 只是确认我的结论,更大的结果意味着更快的 CPU 对吗?我的意思是在这 100 毫秒中进行了更多的数学运算?可能是一些优化或 JIT 的东西吗?
  • 结果越高,数学计​​算最快的就是这个cpu
  • 会不会是过热和某种热节流?

标签: java android math benchmarking computation


【解决方案1】:

过热?不。我怀疑这个计算会让你的 CPU 出汗。

我认为随着时间的推移发生的变化与 JVM 和统计数据有关。 HotSpot 编译器使用它们根据您的代码正在执行的操作来优化代码分支。

http://blog.takipi.com/jvm-performance-magic-tricks/

https://wiki.openjdk.java.net/display/HotSpot/PerformanceTechniques

您知道发生了什么的唯一方法是使用分析器。您需要查看垃圾收集、内存以及花费时间的位置。你的简单基准不会给你那种洞察力。

【讨论】:

  • duffymo,你能帮我解决这个问题吗?无法通过您的链接找到解决问题的方法。非常感谢
  • 我认为您没有要解决的问题。我指出这是 JVM 的工作方式。随着您将更多案例运行到渐近值,时间会缩短。如果您重新启动应用程序,它必须“热身”并积累一个新的统计分支模型。这也是微基准具有欺骗性的原因之一。
  • 所以 duffymo ,解决方案应该是执行 1000 次迭代并只监听最后 500 次的结果?
  • 是的,有些人建议 JVM 有一个“热身”期。 oracle.com/technetwork/articles/java/…
  • 但是,为什么要减少结果而不是增加结果呢?
【解决方案2】:

如果我理解正确,这两个日志 sn-p 是针对不同 JVM 启动的不同执行?

在这种情况下,两者之间的差异不可能是JVM造成的(因为它已经重新启动了)。

因此,差异可能是由很多东西引起的:操作系统文件缓存(已经有一些文件在处理)、CPU 电源管理(CPU 频率在不使用时下降可能需要一些时间才能恢复它是最大频率),在主机上运行的其他东西(如果它是一个虚拟机......可以进行很多事情),CPU 优化(如预取的分支预测),......

不管怎样,你没有问题,这只是目前计算机/jvm/cpu 的工作方式......

【讨论】:

  • wtf,那么如何为android/java做一个benchmark??也是在应用程序的同一执行中,我按了几次工作台按钮来进行这些测试
  • 如果它在同一个 JVM 启动上,它可能是 JVM 内部优化的启动和退出。这很复杂,但 JVM(Hotspot/JIT)会进行一些优化,如果您不使用代码的某些部分,也可能会出现一些反优化。基准测试真的很难,这种微基准测试需要使用基准测试工具来完成,以避免 JVM/OS 优化,而不是在您的应用程序中。检查JMH:openjdk.java.net/projects/code-tools/jmh
猜你喜欢
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多