R:Измерение времени выполнения выражений — различия между версиями
м (→Функция system.time()) |
м (→Функция system.time()) |
||
Строка 8: | Строка 8: | ||
== Функция system.time() == | == Функция system.time() == | ||
− | Самый простой инструмент для измерения времени выполнения кода - функция {{Inline-code|system.time()|lang=rsplus}} из пакета {{Inline-code|base|lang=rsplus}}. В качестве аргумента функция {{Inline-code|system.time()|lang=rsplus}} принимает выражения и возвращает время выполнения данного выражения. Измерим время выполнения функции {{Inline-code|Sys.sleep()|lang=rsplus}}, которая останавливает выполнение кода на заданный интервал времени (в секундах): | + | Самый простой инструмент для измерения времени выполнения кода - функция {{Inline-code|system.time()|lang="rsplus"}} из пакета {{Inline-code|base|lang="rsplus"}}. В качестве аргумента функция {{Inline-code|system.time()|lang="rsplus"}} принимает выражения и возвращает время выполнения данного выражения. Измерим время выполнения функции {{Inline-code|Sys.sleep()|lang="rsplus"}}, которая останавливает выполнение кода на заданный интервал времени (в секундах): |
<syntaxhighlight lang="rsplus"> | <syntaxhighlight lang="rsplus"> | ||
Строка 18: | Строка 18: | ||
Как видим, на выполнение данной операции заняло ровно одну секунду. | Как видим, на выполнение данной операции заняло ровно одну секунду. | ||
− | Приведём ещё один пример. Сравним время вычисления встроенной в R функции ({{Inline-code|mean()|lang=rsplus}}) и среднего, вычисленного по формуле <math>\frac{1}{n}\sum_{i=1}^{n}x_{i}</math>. на сгенерированном массиве нормально распределенных значений: | + | Приведём ещё один пример. Сравним время вычисления встроенной в R функции ({{Inline-code|mean()|lang="rsplus"}}) и среднего, вычисленного по формуле <math>\frac{1}{n}\sum_{i=1}^{n}x_{i}</math>. на сгенерированном массиве нормально распределенных значений: |
<syntaxhighlight lang="rsplus"> | <syntaxhighlight lang="rsplus"> | ||
Строка 31: | Строка 31: | ||
Функция возвращает 3 значения: | Функция возвращает 3 значения: | ||
− | * {{Inline-code|user|lang=rsplus}} - время CPU, которое занял пользователь; | + | * {{Inline-code|user|lang="rsplus"}} - время CPU, которое занял пользователь; |
− | * {{Inline-code|system|lang=rsplus}} - время CPU, которое заняла система; | + | * {{Inline-code|system|lang="rsplus"}} - время CPU, которое заняла система; |
− | * {{Inline-code|elapsed|lang=rsplus}} - реальное время, которое заняло выполнение команды. | + | * {{Inline-code|elapsed|lang="rsplus"}} - реальное время, которое заняло выполнение команды. |
− | Соответственно, в выводе функции нас интересует значение {{Inline-code|elapsed|lang=rsplus}}, который показывает время выполнения функции (выражения) в секундах. Как мы видим, внешне более сложное выражение {{Inline-code|sum(x) / length(x)|lang=rsplus}} выполняется быстрее стандартной функции {{Inline-code|mean(x)|lang=rsplus}}. | + | Соответственно, в выводе функции нас интересует значение {{Inline-code|elapsed|lang="rsplus"}}, который показывает время выполнения функции (выражения) в секундах. Как мы видим, внешне более сложное выражение {{Inline-code|sum(x) / length(x)|lang="rsplus"}} выполняется быстрее стандартной функции {{Inline-code|mean(x)|lang="rsplus"}}. |
− | К сожалению, подобный способ достаточно ненадежен, так как для оценки времени выполнения выражения функция {{Inline-code|system.time()|lang=rsplus}} обращается к системным значениям времени. Следовательно, если во время выполнения кода параллельно производятся и другие операции на компьютере (а такое случается практически в ста процентах случаев), то возможно увеличение времени выполнения R-кода. Некоторую вариативность результатов можно увидеть, даже если выполнить функцию {{Inline-code|system.time()|lang=rsplus}} несколько раз подряд. Подобной неточности оценки можно избежать путём многократного повторения выполняемых выражений и вычислением среднего времени, что позволит сгладить часть вариаций. | + | К сожалению, подобный способ достаточно ненадежен, так как для оценки времени выполнения выражения функция {{Inline-code|system.time()|lang="rsplus"}} обращается к системным значениям времени. Следовательно, если во время выполнения кода параллельно производятся и другие операции на компьютере (а такое случается практически в ста процентах случаев), то возможно увеличение времени выполнения R-кода. Некоторую вариативность результатов можно увидеть, даже если выполнить функцию {{Inline-code|system.time()|lang="rsplus"}} несколько раз подряд. Подобной неточности оценки можно избежать путём многократного повторения выполняемых выражений и вычислением среднего времени, что позволит сгладить часть вариаций. |
Проиллюстрируем вышесказанное на примере: | Проиллюстрируем вышесказанное на примере: | ||
Строка 46: | Строка 46: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | В этом примере с помощью функции {{Inline-code|replicate()|lang=rsplus}} мы повторили выражение {{Inline-code|system.time(mean(x))|lang=rsplus}} 10 раз, отфильтровав вывод функции {{Inline-code|system.time()|lang=rsplus}} так, чтобы нам выводилось только время выполнения команды, дописав {{Inline-code|[["elapsed"]]|lang=rsplus}}. Как мы видим, время выполнения при повторном выполнении выражения может отличаться. | + | В этом примере с помощью функции {{Inline-code|replicate()|lang="rsplus"}} мы повторили выражение {{Inline-code|system.time(mean(x))|lang="rsplus"}} 10 раз, отфильтровав вывод функции {{Inline-code|system.time()|lang="rsplus"}} так, чтобы нам выводилось только время выполнения команды, дописав {{Inline-code|[["elapsed"]]|lang="rsplus"}}. Как мы видим, время выполнения при повторном выполнении выражения может отличаться. |
− | Базовый пакет позволяет реализовать процедуру многократного повторения выражения функции как минимум двумя способами. Первый - функция {{Inline-code|replicate()|lang=rsplus}}. Приведенное выше сопоставление времени выполнения двух выражений при использовании функции {{Inline-code|replicate()|lang=rsplus}} будет выглядеть следующим образом: | + | Базовый пакет позволяет реализовать процедуру многократного повторения выражения функции как минимум двумя способами. Первый - функция {{Inline-code|replicate()|lang="rsplus"}}. Приведенное выше сопоставление времени выполнения двух выражений при использовании функции {{Inline-code|replicate()|lang="rsplus"}} будет выглядеть следующим образом: |
<syntaxhighlight lang="rsplus"> | <syntaxhighlight lang="rsplus"> | ||
Строка 59: | Строка 59: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | Тот же самый эффект можно получить и с помощью обычного цикла {{Inline-code|for()|lang=rsplus}}: | + | Тот же самый эффект можно получить и с помощью обычного цикла {{Inline-code|for()|lang="rsplus"}}: |
<syntaxhighlight lang="rsplus"> | <syntaxhighlight lang="rsplus"> | ||
Строка 70: | Строка 70: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | Вместо подобных решений можно использовать специальные пакеты, предназначенные для измерения производительности кода, в частности, пакеты {{Inline-code|rbenchmark|lang=rsplus}} и {{Inline-code|microbenchmark|lang=rsplus}}. Основной принцип работы этих пакетов заключается в многократном выполнении выражений и расчёта ряда интегральных показателей, в частности, суммы, среднего значения или медианы времени выполнения всех попыток. | + | Можно также использовать описательные статистики в сочетании с множественными повторениями: |
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | > median(replicate(100, system.time(mean(x))[["elapsed"]])) | ||
+ | [1] 0.021 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | В примере выше мы взяли только значения {{Inline-code|elapsed|lang="rsplus"}} и рассчитали медиану <ref>Медиана является более устойчивой мерой центральной тенденции при асимметрии распределения, что, как правило, характерно для измерения времени.</ref>. | ||
+ | |||
+ | Вместо подобных решений можно использовать специальные пакеты, предназначенные для измерения производительности кода, в частности, пакеты {{Inline-code|rbenchmark|lang="rsplus"}} и {{Inline-code|microbenchmark|lang="rsplus"}}. Основной принцип работы этих пакетов заключается в многократном выполнении выражений и расчёта ряда интегральных показателей, в частности, суммы, среднего значения или медианы времени выполнения всех попыток. | ||
== Пакет rbenchmark == | == Пакет rbenchmark == |
Версия 19:31, 22 января 2014
|
Материал «R:Измерение времени выполнения выражений», созданный автором Артём Клевцов, публикуется на условиях лицензии Creative Commons «Attribution» («Атрибуция») 4.0 Всемирная. | |
|
Для измерения времени выполнения выражений используют следующие инструменты:
- Функция Шаблон:Inline-code из базового пакета;
- Cпециализированные функции (benchmarks, бенчмарки);
- Функция профилирования времени выполнения кода Шаблон:Inline-code.
Функция system.time()
Самый простой инструмент для измерения времени выполнения кода - функция Шаблон:Inline-code из пакета Шаблон:Inline-code. В качестве аргумента функция Шаблон:Inline-code принимает выражения и возвращает время выполнения данного выражения. Измерим время выполнения функции Шаблон:Inline-code, которая останавливает выполнение кода на заданный интервал времени (в секундах):
<syntaxhighlight lang="rsplus"> > system.time(Sys.sleep(1)) пользователь система прошло
0.003 0.004 1.000
</syntaxhighlight>
Как видим, на выполнение данной операции заняло ровно одну секунду.
Приведём ещё один пример. Сравним время вычисления встроенной в R функции (Шаблон:Inline-code) и среднего, вычисленного по формуле [math]\frac{1}{n}\sum_{i=1}^{n}x_{i}[/math]. на сгенерированном массиве нормально распределенных значений:
<syntaxhighlight lang="rsplus"> > x <- rnorm(10^7L) > system.time(mean(x)) пользователь система прошло
0.020 0.000 0.022
> system.time(sum(x) / length(x)) пользователь система прошло
0.013 0.000 0.013
</syntaxhighlight>
Функция возвращает 3 значения:
- Шаблон:Inline-code - время CPU, которое занял пользователь;
- Шаблон:Inline-code - время CPU, которое заняла система;
- Шаблон:Inline-code - реальное время, которое заняло выполнение команды.
Соответственно, в выводе функции нас интересует значение Шаблон:Inline-code, который показывает время выполнения функции (выражения) в секундах. Как мы видим, внешне более сложное выражение Шаблон:Inline-code выполняется быстрее стандартной функции Шаблон:Inline-code.
К сожалению, подобный способ достаточно ненадежен, так как для оценки времени выполнения выражения функция Шаблон:Inline-code обращается к системным значениям времени. Следовательно, если во время выполнения кода параллельно производятся и другие операции на компьютере (а такое случается практически в ста процентах случаев), то возможно увеличение времени выполнения R-кода. Некоторую вариативность результатов можно увидеть, даже если выполнить функцию Шаблон:Inline-code несколько раз подряд. Подобной неточности оценки можно избежать путём многократного повторения выполняемых выражений и вычислением среднего времени, что позволит сгладить часть вариаций.
Проиллюстрируем вышесказанное на примере:
<syntaxhighlight lang="rsplus"> > replicate(10, system.time(mean(x))"elapsed")
[1] 0.023 0.021 0.021 0.021 0.022 0.021 0.022 0.021 0.021 0.021
</syntaxhighlight>
В этом примере с помощью функции Шаблон:Inline-code мы повторили выражение Шаблон:Inline-code 10 раз, отфильтровав вывод функции Шаблон:Inline-code так, чтобы нам выводилось только время выполнения команды, дописав Шаблон:Inline-code. Как мы видим, время выполнения при повторном выполнении выражения может отличаться.
Базовый пакет позволяет реализовать процедуру многократного повторения выражения функции как минимум двумя способами. Первый - функция Шаблон:Inline-code. Приведенное выше сопоставление времени выполнения двух выражений при использовании функции Шаблон:Inline-code будет выглядеть следующим образом:
<syntaxhighlight lang="rsplus"> > system.time(replicate(100, mean(x))) пользователь система прошло
2.166 0.000 2.162
> system.time(replicate(100, sum(x) / length(x))) пользователь система прошло
1.167 0.003 1.186
</syntaxhighlight>
Тот же самый эффект можно получить и с помощью обычного цикла Шаблон:Inline-code:
<syntaxhighlight lang="rsplus"> > system.time(for (i in seq_len(100)) mean(x)) пользователь система прошло
2.110 0.003 2.126
> system.time(for (i in seq_len(100)) sum(x) / length(x)) пользователь система прошло
1.070 0.000 1.085
</syntaxhighlight>
Можно также использовать описательные статистики в сочетании с множественными повторениями:
<syntaxhighlight lang="rsplus"> > median(replicate(100, system.time(mean(x))"elapsed")) [1] 0.021 </syntaxhighlight>
В примере выше мы взяли только значения Шаблон:Inline-code и рассчитали медиану [1].
Вместо подобных решений можно использовать специальные пакеты, предназначенные для измерения производительности кода, в частности, пакеты Шаблон:Inline-code и Шаблон:Inline-code. Основной принцип работы этих пакетов заключается в многократном выполнении выражений и расчёта ряда интегральных показателей, в частности, суммы, среднего значения или медианы времени выполнения всех попыток.
Пакет rbenchmark
Пакет microbenchmark
Примечания
- ↑ Медиана является более устойчивой мерой центральной тенденции при асимметрии распределения, что, как правило, характерно для измерения времени.