3482
правки
Изменения
м
> s <- as.double(0)> x <- as.double(1:1000)
> expr <- expression(for (i in x) s <- s + i)> exprc <- compile(for (i in x) s <- s + i)
> identical(eval(expr), eval(exprc))#> [1] TRUE
> microbenchmark(eval(expr), eval(exprc))#> Unit: microsecondsnanoseconds#> expr min lq median uq uq max neval#> eval(expr) 315.05 323.438 329.628 338.978 365.631 191031 200750 205432 210436 291039 100#> eval(exprc) 924 1.58 1202 1.883 1346 2.199 2.482 8.311 1628 11845 100</nowiki>}}
Загрузка 2881-compilation.wiki
<!-- R:Оптимизация/Компиляция в байт-код -->
{{CC-BY-4.0|author=автором Артём Клевцов}}
Рассмотрим эти опции:
* <code>optimize</code> --- определяет уровень оптимизации: принимает значения от 0 до 3 (по умолчанию 2);* <code>suppressAll</code> --- управляет сообщениями: принимает значения <code>TRUE</code> или <code>FALSE</code> (по умолчанию code>FALSE</code>);* <code>suppressUndefined</code> --- управление сообщения о неопределённых (undefined) переменных: может принимать значения <code>TRUE</code> или список имён переменных (по умолчанию ".Generic", .Method", ".Random.seed", ".self").
Получить текущее значение глобальных опций компиляции можно с помощью функции <code>getCompilerOption()</code>:
{{r-code|code=<nowiki>> getCompilerOption("optimize")#> [1] 2> getCompilerOption("suppressAll")#> [1] FALSE> getCompilerOption("suppressUndefined")#> [1] ".Generic" ".Method" ".Random.seed" ".self"</nowiki>}}
== Компиляция функций и выражений ==
{{r-code|code=<nowiki># объявляем переменные
# объявляем выражения
# сравниваем результат работы выражений
# сравниваем производительность выражений
Компиляция функций осуществляется с помощью функции <code>cmpfun()</code>. Возьмём пример из документации к функции <code>cmpfun()</code>, вкотором предлагается сравнить производительность различных реализаций функции <code>lapply()</code>, а также их скомпилированных версий:
for(i in seq(along = X))
rval[i] <- list(FUN(X[[i]], ...))
names(rval) <- names(X) # keep `names' !
return(rval)
}
rval[[i]] <- v
}
names(rval) <- names(X) # keep `names' !
return(rval)
}</nowiki>}}
Скомпилируем эти функции в бат-код:
{{r-code|code=<nowiki>> la1c <- cmpfun(la1)> la2c <- cmpfun(la2)> lapplyc <- cmpfun(lapply)</nowiki>}}
Сравним производительность этих функций:
{{r-code|code=<nowiki>> x <- 1:1000> microbenchmark(lapply(x, is.null), la1(x, is.null), la2(x, is.null),+ lapplyc(x, is.null), la1c(x, is.null), la2c(x, is.null))#> Unit: microseconds#> expr min lq median uq max neval#> lapply(x, is.null) 174173.1 181 183.2 196193.4 229205.5 2 946 294.4 100#> la1(x, is.null) 786792.0 8163 836.2 1 838861.6 1 985929.9 1807.6 1812 100#> la2(x, is.null) 967965.6 9960 1012.9 1 1036.6 1085.8 1359.9 2417 2769.5 100#> lapplyc(x, is.null) 173171.5 182.4 181 189.1 196200.8 3 214265.7 333 6 100#> la1c(x, is.null) 392394.0 4092 416.8 0 433428.8 0 502446.3 1400 9 1217.8 100#> la2c(x, is.null) 403397.6 415 424.6 5 439.7 1 532457.1 1361 2 1216.0 100</nowiki>}}
Обращается на себя внимание, что скомпилированная версия функции <code>lapply()</code> не превосходит по производительности оригинальную версию. Происходит это потому, что функция <code>lapply()</code> использует написанную на C, скомпилированную функцию. Также отметим, что скомпилированные версии функций <code>la1()</code> и <code>la2()</code> показываются практически одинаковую производительность, тогда как нескомпилированные версии довольно сильно различались. Это достигается за счёт высокой оптимизации работы циклов при компиляции функций.
Ещё одна возможность, предоставляемая пакетом {{r-package|compiler|core=true}} - это компиляция R-скриптов. Создание скомпилированных файлов осуществляется с помощью функции \texttt{cmpfile()}, а загрузка скомпилированных файлов с помощью функции <code>loadcmp()</code>. Если выходной файл не указан, то выходной файл имеет тоже имя, что и входной, но с расширением <code>.Rc</code>. Пример использования:
{{r-code|code=<nowiki>> cmpfile("script.R", "script.Rc")> loadcmp("script.Rc")</nowiki>}}
== JIT-компиляция ==