2013-12-12 1 views
0

Я пытаюсь сравнить точность методов синхронизации с C++ и Java.Временной блок кода с C++ и Java

С C++ Я обычно использую CLOCKS_PER_SEC, я запускаю блок кода. Я хочу время на определенное время, а затем вычислить, сколько времени потребовалось, в зависимости от того, сколько раз блок выполнялся.

С Java Я обычно использую System.nanoTime().

Какой из них более точный, тот, который я использую для C++ или тот, который я использую для Java? Есть ли другой способ времени на C++, поэтому мне не нужно повторять фрагмент кода, чтобы получить правильное измерение? В принципе, существует ли метод System.nanoTime() для C++?

Я знаю, что оба используют системные вызовы, которые вызывают значительные задержки. Как это искажает реальную ценность времени? Есть ли способ предотвратить это?

ответ

0

У каждого метода есть ошибки. Прежде чем вы потратите много времени на этот вопрос, вы должны спросить себя: «Насколько точным мне нужен мой ответ»? Обычно решение состоит в том, чтобы запускать цикл/кусок кода несколько раз и отслеживать среднее/стандартное отклонение измерения. Это хороший способ справиться с повторяемостью ваших измерений. После этого предположим, что время ожидания «сопоставимо» между вызовами «время начала» и «время остановки» (независимо от того, какую функцию вы использовали), и у вас есть основа для понимания проблем.

Нижняя линия: clock() Функция обычно дает точность в микросекунду.

См. https://stackoverflow.com/a/20497193/1967396 для примера того, как это сделать в C (в этом случае, используя часы точности usec). Существует возможность использования ns-времени - см., Например, ответ на clock_gettime() still not monotonic - alternatives?, который использует clock_gettime(CLOCK_MONOTONIC_RAW, &tSpec);

Обратите внимание, что вам нужно извлечь секунды и наносекунды отдельно от этой структуры.

+0

Можете ли вы действительно обосновать точность метода, отслеживая стандартное отклонение при циклировании в процессе? Ваш процесс, скорее всего, не единственный процесс, запущенный в системе, и планировщик должен быть свободен, чтобы дать ему время, когда он это чувствует. – user

+1

Я сказал, что стандартное отклонение даст вам описание ** повторяемости **: если вы делаете это несколько раз, вы получаете тот же ответ (почти то же, что и «точность»). Это отличается от ** точности **: это правильный ответ. Вы не можете знать это без калибровки. Извините за то, что вы новичок в номенклатуре. – Floris

+1

@ bruce14 - другое примечание - большинство часов, которые предоставляются (кроме часов настенных часов), измеряют время, прошедшее в процессе, поэтому они компенсируют время, в течение которого ваш процесс был приостановлен. «Getrusage()» особенно эффективен в этом отношении. – Floris

0

Будьте осторожны с использованием System.nanoTime(), поскольку он по-прежнему ограничен разрешением, которое может дать вам машина.

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

Практически все современные системы используют упреждающую многопоточность и несколько ядер и т. Д. - поэтому все тайминги будут варьироваться от run to run. (Например, если управление отключается от вашего потока, пока оно находится в методе).

Чтобы получить надежные тайминги вам нужно

  1. разогреть систему, бегая вокруг вещи вы синхронизации несколько сотен раз, прежде чем начать.
  2. Запустите код для хорошего количества раз и усредните результаты.

Вопросы надежности одинаковы для любого языка, поэтому применимы так же хорошо, как и к Java, поэтому C может не понадобиться цикл разогрева, но вам все равно придется брать много образцов и усреднять их.

+1

Хороший способ показать эффект «разогрева» (особенно заметный, когда вы подключаете сетевые подключения, но даже кэш памяти может играть) заключается в записи (общего) прошедшего времени после каждого цикла, а затем постройте эти значения против количества циклов ,Наклон этой кривой может увеличиться для первых нескольких итераций, а затем стабилизироваться. Полагаю, это именно тот эффект, который вы описываете. – Floris

+1

Кэширование и т. Д. Может дать некоторый эффект «разогрева» даже в C. В Java эффект гораздо более заметен из-за Just In Time Compilation. Первые несколько раз вокруг него работает байт-код, затем постепенно все больше и больше кода превращается в ассемблер, настроенный для среды, в которой он работает. –

+0

В соответствии со стандартом время от 'clock()' должно быть временем процессора, используемым вашим приложением, поэтому включение, а затем обратно не должно влиять на него. (В этом случае нарушена реализация 'clock()' Windows. Конечно, прерывание другого процесса, а затем продолжение, может повлиять на объем вашей памяти процесса в кеше, что, в свою очередь, влияет на производительность. –