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