Временные функции в R [закрыто]

36
  1. Я хотел бы измерить время, необходимое для повторного запуска функции. replicate()Эквивалентны ли циклы for и используются ли они ? Например:

    system.time(replicate(1000, f()));
    system.time(for(i in 1:1000){f()});
    

    Какой предпочтительный метод.

  2. В выводе system.time(), является sys+userфактическое время процессора для запуска программы? Является elapsedли хорошим показателем времени выполнения программы?

Тим
источник
3
Просто для справки, так как я явно слишком опоздал, чтобы изменить ход этого вопроса: я думаю, что эта проблема лучше всего подходит для StackOverflow.
Мэтт Паркер
2
@ Matt Я согласен, что вопросы о том, как один раз программа хорошо подходит для SO. Я также согласен с тем, что буквальное толкование этого вопроса (как принято несколькими ответами) поставило бы его не по теме здесь, в резюме. По-видимому, существует некоторый статистический интерес к разработке временного эксперимента и анализу результатов такого эксперимента.
whuber

Ответы:

19

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

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

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

Whuber
источник
25

Относительно ваших двух пунктов:

  1. Это стилистично. Мне нравится, replicate()как это функционально.
  2. Я стремлюсь сосредоточиться elapsed, т.е. на третьем номере.

Что я часто делаю

N <- someNumber
mean(replicate( N, system.time( f(...) )[3], trimmed=0.05) )

чтобы получить усеченное среднее из 90% N повторений вызова f().

(Отредактировано, спасибо Хэдли за то, что он поймал мысли.)

Дирк Эддельбюттель
источник
2
Ты имеешь в виду mean(replicate(N, system.time(f(...))[3]), trim = 0.05)?
хэдли
2
Если вызов f () длинный, то это нормально. Тем не менее, если вызов f () короткий, то любые издержки временного вызова, вероятно, будут увеличивать погрешность измерения. С помощью одного вызова system.time () во многих повторениях функции f () можно разделить ошибку на вызов до некоторого бесконечно малого значения (и оно возвращается быстрее).
Джон
@John: Спасибо, но я не совсем понимаю, что вы сказали. Мне все еще интересно, что лучше, повторяя f () внутри или снаружи system.time ()?
Тим
Каждый вызов команды system.time () имеет переменное время, необходимое для вызова, что вызывает определенную ошибку измерения. Это небольшое количество. Но что если f () - очень короткий вызов? Тогда эту ошибку можно сопоставить со временем, затраченным на вызов f (). Таким образом, когда вы вызываете f () 1e5 раз внутри одного вызова system.time (), ошибка делится на 1e5 кусков. Когда вы вызываете system.time () для каждого f (), это влияние может быть значимым, если время для f () мало. Конечно, если вам нужно только относительное время, это не имеет большого значения.
Джон
Да, и вторая часть заключается в том, что было бы быстрее просто вызвать system.call () один раз.
Джон
10

Вы можете также время с временными шагами, возвращенными Sys.time; это, конечно, измеряет настенное время, поэтому время вычислений в реальном времени. Пример кода:

Sys.time()->start;
replicate(N,doMeasuredComputation());
print(Sys.time()-start);

источник
3

Относительно того, какой показатель времени использовать, я не могу добавить к другим респондентам.

Что касается используемой функции, мне нравится использовать? Benchmark из пакета rbenchmark .

Таль Галили
источник
1

Они делают разные вещи. Время, что вы хотите сделать. replicate () возвращает вектор результатов каждого выполнения функции. Цикл для не делает. Следовательно, они не являются эквивалентными утверждениями.

Кроме того, время ряд способов вы хотите что-то сделать. Тогда вы сможете найти наиболее эффективный метод.

Джон
источник
mod-tip: опубликовать вторую часть как комментарий к ответу Дирка.