Почему детерминированный алгоритм в Java работает в разное время? - PullRequest
2 голосов
/ 01 апреля 2011

У меня есть программа на Java, которая вычисляет проблему n-тела.На каждой итерации он проверяет силы, которые каждое тело оказывает на каждое другое тело, а затем перемещает их в соответствии с силами.

Тела всегда начинаются в одном и том же месте (у меня они расположены по кругу, от тела 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?

Ответы [ 3 ]

1 голос
/ 01 апреля 2011

Сравнение многопоточных программ может быть сложной задачей из-за динамической компиляции, сборки мусора и адаптивной оптимизации. Я предлагаю прочитать главу 12 «Практического параллелизма Java» Брайана Гетца.

1 голос
/ 01 апреля 2011

Вы уверены, что правильно измеряете время? Внутри jvm может быть много потоков, которые не видны вам как пользователю. Если вы получаете системное время, то вы игнорируете существование этих потоков. Кроме того, если вы запускаете какие-либо другие потоки, вы можете игнорировать время их добавления.

0 голосов
/ 01 апреля 2011

Предполагая, что поток, который вы синхронизируете, является лишь одним из многих потоков, просто получение разности времени начала и конца вычислений в потоке на самом деле не измеряет фактическое время ЦП, затраченное потоком.Он конкурирует с другими потоками и должен был бы приостанавливать / ждать, пока другие потоки работают, но вы также будете считать время ожидания.

Поскольку планирование потоков может отличаться, и мы также должны учитывать сборку мусора, общее время, затрачиваемое от начала до конца потока, может сильно различаться.Но фактическое количество процессорного времени не изменится.

Редактировать :

Я думаю, что вам нужно измерить количество времени, потраченное потоком в пользовательском режиме,Это должно избавить от времени, потраченного на ожидание OS / JVM, и измерять только время, потраченное на выполнение в потоке.Итак, попробуйте использовать getCurrentThreadUserTime.

Я обнаружил более ранний поток SO об этом: Разница между временем пользователя потока и временем процессора в Java

...