Функції синхронізації в 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

Для ефективного таймінгу програм, особливо коли вам цікаво порівняти альтернативні рішення, вам потрібен контроль! Хороший спосіб - ввести у функцію процедуру, яку ви призначаєте. Виклик функції в циклі синхронізації. Напишіть процедуру заглушки, по суті, вилучивши весь код зі своєї функції та просто повернувшись із неї (але залиште всі аргументи у). Поставте заглушку у цикл синхронізації та повторіть час. Це вимірює всі накладні витрати, пов'язані з термінами. Відняти час заглушки від часу процедури, щоб отримати сітку: це має бути точним показником фактичного необхідного часу.

Оскільки більшість систем в даний час може бути перервано безперервно, важливо зробити кілька запусків часу, щоб перевірити їх мінливість. Замість того, щоб робити один довгий пробіг з секунд, робіть пробігу приблизно секунд кожна. Це допомагає зробити це в подвійній петлі все за один раз. Мало того, що простіше впоратися, це вводить трохи негативної кореляції у кожному часовому ряді, що фактично покращує оцінки.м н / мNмN/м

Використовуючи ці основні принципи експериментального дизайну, ви по суті контролюєте будь-які відмінності через те, як ви розгортаєте код (наприклад, різницю між циклом for та реплікацією ()). Це змушує вашу проблему піти.


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

Щодо того, який метрику часу використовувати, я не можу додати до інших респондентів.

Щодо функції, яку потрібно використовувати, мені подобається використовувати показник? З пакету rbenchmark .


1

Вони роблять різні речі. Час, що ви хочете зробити. replicate () повертає вектор результатів кожного виконання функції. Цикл for не робить. Тому вони не є рівнозначними твердженнями.

Крім того, приділіть кілька способів зробити щось, що потрібно зробити. Тоді ви зможете знайти найбільш ефективний метод.


mod-tip: опублікуйте другу частину як коментар до відповіді Дірка.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.