2016-03-15 3 views
3

Как измерить время выполнения метода в ECLiPSe CLP? В настоящее время у меня есть это:Измерение времени выполнения ECLiPSe CLP (или Prolog)

measure_traditional(Difficulty,Selection,Choice):- 
    statistics(runtime, _), 
    time(solve_traditional(Difficulty,Selection,Choice,_)), 
    time(solve_traditional(Difficulty,Selection,Choice,_)), 
    time(solve_traditional(Difficulty,Selection,Choice,_)), 
    time(solve_traditional(Difficulty,Selection,Choice,_)), 
    time(solve_traditional(Difficulty,Selection,Choice,_)), 
    time(solve_traditional(Difficulty,Selection,Choice,_)), 
    time(solve_traditional(Difficulty,Selection,Choice,_)), 
    time(solve_traditional(Difficulty,Selection,Choice,_)), 
    statistics(runtime,[_|T]), % T 
    write(T). 

Мне нужно написать время, которое потребовалось, чтобы выполнить метод solve_traditional (...) и записать его в текстовый файл. Однако это недостаточно точно. Иногда время будет печатать 0.015 или 0.016 секунд для данного метода, но обычно он печатает 0.0 секунд.

Полагая, что метод выполняется слишком быстро, я решил использовать статистику (runtime, ...) для измерения времени, которое требуется между двумя вызовами времени выполнения. Затем я мог бы измерить, например, время, необходимое для завершения 20 вызовов метода и деления измеренного времени T на 20.

Только проблема состоит в том, что 20 вызовов T равны либо 0, 16, 32, либо 48 миллисекунд. По-видимому, он измеряет время для каждого вызова метода отдельно и находит сумму времени выполнения (которое часто составляет всего 0,0 с). Это превосходит всю цель измерения времени выполнения для N вызовов метода и деления времени T на N.

Одним словом: текущие методы, которые я использую для измерения времени выполнения, являются недостаточными. Есть ли способ сделать его более точным (например, 9 десятичных знаков)?

+0

Вместо измерения 'once (Goal)', напишите '\ + (между (1, F, _), \ + Goal)' с установленным 'F' соответствующим образом – false

ответ

5

Бенчмаркинг - сложный бизнес на любом языке программирования, и особенно в CLP. Особенно, если вы планируете публиковать свои результаты, вы должны быть предельно тщательными и абсолютно уверены, что вы измеряете то, что вы утверждаете для оценки.

Таймеры: Вы измерения в реальном масштабе времени, процесс времени центрального процессора, нить процессорное время? Включая время, затрачиваемое на системные вызовы? Включая или исключая сбор мусора? ...

См. Различные таймеры, предлагаемые примитивом statistics/2. Существует таймер с высоким разрешением в реальном времени, к которому можно получить доступ через statistics(hr_time,T).

разрешение таймера: В вашем примере разрешение таймера, кажется, 1/60 сек. Это означает, что для измерения времени 3 важных цифры необходимо измерить, по крайней мере, время работы 1000 * 1/60 = 16,7 секунды.

Если ваше тестовое время слишком короткое, вы должны запускать его несколько раз.

Продолжительность разница: На современных машинах это становится все труднее получить воспроизводимые тайминги. Это происходит из-за эффекты, которые не имеют ничего общего с программой вы измеряете, например, поведение кэша, пейджинг, переключения контекста, аппаратные средства управления питанием, выравнивание памяти и т.д.

Run достаточно повторений, бегите на тихом убедитесь, что ваши результаты воспроизводимы.

Повторных тесты: В системе, как ECLIPSE, бегущие тесты неоднократно должны быть сделаны тщательно, чтобы гарантировать, что последовательные пробеги действительно делают то же вычисление, и в идеале иметь такое же или подобное поведение кэша и вывоз мусора.

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

run_n_times(N,Goal) :- \+ (between(1,N,1,_), \+ Goal). 

, который по существу представляет собой способ повторить п раз последовательность

once(Goal), fail 

Смысл этого в том, что сочетание once/1 и fail расстегивает все Goal , так что следующая итерация начинается как можно больше от аналогичного состояния машины. К сожалению, это само по себе отмена процесса добавляет дополнительную среду выполнения, которая искажает измерение ...

Контрольные накладные расходы: Если вы запустите эталонные несколько раз, вы должны рамки тест, который делает, что для вас, и это способствует измерению времени выполнения.

Вы либо должны убедиться, что накладные расходы незначительны, или вы должны измерить нагрузку (например, путем запуска тестовой базы с фиктивным эталоном) и вычесть его, например:

benchmark(N, DummyGoal, Goal, Time) :- 
    cputime(T1), 
    run_n_times(N, DummyGoal), 
    cputime(T2), 
    run_n_times(N, Goal), 
    cputime(T3), 
    Time is (T3-T2)-(T2-T1). 

Спецификация CLP: Существует множество других соображений, специфичных для операций, управляемых данными, которые возникают в решателях CLP, и которые затрудняют сравнение CLP-времени выполнения. Эти решатели имеют много внутренних степеней свободы в отношении планирования пропагандистов, степени обрезке, связать нарушение правил в управлении поиска и т.д.

документ, который обсуждает эти вещи конкретно это: На Бенчмаркинг Constraint Logic Программирование платформ, Марк Уоллес, Йоахим Шимпф, Киш Шен и Уорик Харви. В CONSTRAINTS Journal, изд. E.C. Freuder, 9 (1), pp. 5-34, Kluwer, 2004.

+0

Я все еще возвращаюсь к этому ответу так часто, чтобы повторите то, что я узнал из вашего поста. Большое спасибо за тщательное и ясное объяснение! – Babyburger

Смежные вопросы