2

我有一个计算 n 体问题的 Java 程序。在每次迭代中,它都会检查每个物体对其他物体施加的力,然后根据这些力移动它们。

身体总是从同一个地方开始(我把它们排列成一个圆圈,从身体 0 到身体 n),它们总是被检查并以相同的顺序移动(从身体 0 到 n)。但是,当我运行该程序 30 次时,我得到的运行时间截然不同。一个运行时间为 2,947,188 毫秒(49 分钟),而另一个运行时间为 920,967 毫秒(15 分钟)。我对这些时间的数量级并不感到惊讶,因为我在很多物体上使用了蛮力方法 (O(n^2))。但我想知道为什么确定性算法会有这样的差异?如果一次又一次使用相同的算法,那么运行时间不应该相同(或至少接近)吗?

在你问之前,是的,我正在测量进行计算的线程的时间,而不是挂钟时间。

编辑-我正在这样测量时间:

ThreadMXBean bean = ManagementFactory.getThreadMXBean();
long startUserTimeNano = bean.getCurrentThreadCpuTime();

// ... Code to do the stuff...

double taskUserTimeNano = (bean.getCurrentThreadCpuTime() - startUserTimeNano);
CPUmillisecondsElapsed += taskUserTimeNano/1000000.0;

除了计算步骤之外,这是否测量任何其他内容?

第二次编辑-现在我将其更改为像这样测量时间:

ThreadMXBean bean = ManagementFactory.getThreadMXBean();
long startUserTimeNano = bean.getCurrentThreadUserTime();

// ... Code to do the stuff...

double taskUserTimeNano = (bean.getCurrentThreadUserTime() - startUserTimeNano);
CPUmillisecondsElapsed += taskUserTimeNano/1000000.0;

然而,结果仍然不可重复。我还尝试使用标志 -Xint 运行我的程序,结果仍然不可重复。

假设问题出在算法和多线程中是否安全?或者它仍然是与Java有关的问题吗?

4

3 回答 3

1

由于动态编译、垃圾收集和自适应优化,对多线程程序进行基准测试可能具有挑战性。我建议阅读 Brian Goetz 的“Java Concurrency in Practice”的第 12 章。

于 2011-04-01T18:57:14.183 回答
1

你确定你测量的时间正确吗?在 jvm 中运行的许多线程对于您作为用户是不可见的。如果您获得系统时间,那么您将忽略这些线程的存在。此外,如果您正在运行任何其他线程,您可能会忽略它们添加的时间。

于 2011-04-01T18:55:04.110 回答
0

假设您正在计时的线程只是众多线程之一,那么简单地获取线程中计算的开始时间和结束时间的差异实际上并不能测量线程实际占用的 CPU 时间。它与其他线程竞争,并且在其他线程运行时必须挂起/等待,但您也会计算它等待的时间。

由于线程的调度方式可能会有所不同,而且我们还必须考虑垃圾收集,因此线程从开始到结束所花费的总时间可能会有很大差异。但实际所需的 CPU 时间量不会改变。

编辑

我认为您需要衡量的是线程在用户模式下花费的时间。这应该消除等待 OS/JVM 所花费的时间,并且只测量在线程中运行所花费的时间。所以,尝试使用getCurrentThreadUserTime.

我发现了一个较早的SO线程:Java中线程用户时间和线程cpu时间之间的差异

于 2011-04-01T19:05:13.720 回答