R:Оптимизация/Предварительное выделение памяти — различия между версиями
(Новая страница: «== Предварительное выделение памяти == Частой задачей, решаемой с помощью циклов, являетс…») |
м (Загрузка 2820-prealloc.wiki) |
||
(не показано 13 промежуточных версий этого же участника) | |||
Строка 1: | Строка 1: | ||
− | + | <!-- R:Оптимизация/Предварительное выделение памяти --> | |
+ | |||
+ | |||
+ | |||
+ | {{CC-BY-4.0|author=автором Артём Клевцов}} | ||
+ | |||
+ | {{Pkg-req-notice}} | ||
Частой задачей, решаемой с помощью циклов, является выполнение расчётов и занесение результатов в переменную. Таким образом, результирующая переменная будет заполняться данными по мере работы цикла. Предварительное выделение памяти (preallocate) позволяет ускорить работу циклов, работающих с постепенной заполняемыми данными. Суть данного метода заключается в том, чтобы заранее выделить место в оперативной памяти, в которую будут записываться данные во время работы цикла. Выделение памяти осуществляется путём указания типа и размера переменной. Если этого не сделать, то при каждой новой итерации необходимо выделять новое место в памяти и производить туда запись. | Частой задачей, решаемой с помощью циклов, является выполнение расчётов и занесение результатов в переменную. Таким образом, результирующая переменная будет заполняться данными по мере работы цикла. Предварительное выделение памяти (preallocate) позволяет ускорить работу циклов, работающих с постепенной заполняемыми данными. Суть данного метода заключается в том, чтобы заранее выделить место в оперативной памяти, в которую будут записываться данные во время работы цикла. Выделение памяти осуществляется путём указания типа и размера переменной. Если этого не сделать, то при каждой новой итерации необходимо выделять новое место в памяти и производить туда запись. | ||
Строка 5: | Строка 11: | ||
Обратите внимание, что переменные, участвующие в цикле, должны быть объявлены до того, как будут использоваться. | Обратите внимание, что переменные, участвующие в цикле, должны быть объявлены до того, как будут использоваться. | ||
− | {{r-code|code=<nowiki | + | {{r-code|code=<nowiki>noaaloc <- function(n) { |
− | + | x <- NULL # объявляем пустую переменную | |
− | + | for (i in seq_len(n)) | |
− | + | x[i] <- i * i | |
− | + | x | |
− | + | } | |
− | + | ||
− | + | alloc <- function(n) { | |
− | + | x <- integer(n) # объявляем переменную нужного типа и размера | |
− | + | for (i in seq_len(n)) | |
− | + | x[i] <- i * i | |
− | + | x | |
− | + | } | |
− | > microbenchmark(noaaloc(10^4), alloc(10^4)) | + | </nowiki>}} |
− | Unit: milliseconds | + | |
− | expr min lq median uq | + | Теперь срвним время выполнения объявленных функций: |
− | noaaloc(10^4) | + | |
− | alloc(10^4) 5. | + | {{r-code|code=<nowiki>microbenchmark(noaaloc(10^4), alloc(10^4)) |
+ | #> Unit: milliseconds | ||
+ | #> expr min lq median uq max neval | ||
+ | #> noaaloc(10^4) 38.545 39.596 39.977 40.595 78.476 100 | ||
+ | #> alloc(10^4) 5.546 5.843 6.112 6.443 7.593 100 | ||
+ | </nowiki>}} | ||
+ | |||
+ | == Создание пустых объектов в R == | ||
+ | |||
+ | === Векторы === | ||
+ | |||
+ | {| class="prettytable wide" | ||
+ | |- | ||
+ | | <code>integer(n)</code> || создаёт объект типа <code>integer</code> ([http://ru.wikipedia.org/wiki/Число_с_фиксированной_запятой число с фиксированной запятой]) длинной <code>n</code>. | ||
+ | |- | ||
+ | | <code>numeric(n)</code> || создаёт объект типа <code>double</code> ([http://ru.wikipedia.org/wiki/Числа_с_плавающей_запятой число с плавающей запятой]) длинной <code>n</code><ref>Эквивалент функции <code>double()</code></ref>. | ||
+ | |- | ||
+ | | <code>double(n)</code> || создаёт объект типа <code>double</code> ([http://ru.wikipedia.org/wiki/Числа_с_плавающей_запятой число с плавающей запятой]) длинной <code>n</code> ([http://ru.wikipedia.org/wiki/Число_двойной_точности число двойной точности]). | ||
+ | |- | ||
+ | | <code>single(n)</code> || создаёт объект типа <code>double</code> ([http://ru.wikipedia.org/wiki/Числа_с_плавающей_запятой число с плавающей запятой]) длинной <code>n</code> ([http://ru.wikipedia.org/wiki/Число_одинарной_точности число одинарной точности]). | ||
+ | |- | ||
+ | | <code>complex(n)</code> || создаёт объект типа <code>complex</code> ([http://ru.wikipedia.org/wiki/Комплексный_тип_данных комплексный тип данных]) длинной <code>n</code>. | ||
+ | |- | ||
+ | | <code>character(n)</code> || создаёт объект типа <code>character</code> ([http://ru.wikipedia.org/wiki/Строковый_тип строковый тип данных]) длинной <code>n</code>. | ||
+ | |- | ||
+ | | <code>logical(n)</code> || создаёт объект типа <code>logical</code> ([http://ru.wikipedia.org/wiki/Логический_тип логический тип данных]) длинной <code>n</code>. | ||
+ | |} | ||
+ | |||
+ | Создание любого типа вектора можно также осуществить с помощью функции <code>vector()</code>. Данная функция принимает два аргумента: <code>mode</code>, указывающая тип данных и <code>length</code>, указывающая длину вектора. Например, создание вектора целых чисел, длиной 100 можно создать с помощью следующих команд: | ||
+ | |||
+ | {{r-code|code=<nowiki>x <- integer(100) | ||
+ | x <- vector("integer", 100) | ||
+ | </nowiki>}} | ||
+ | |||
+ | === Списки === | ||
+ | |||
+ | Списки можно создавать с помощью уже рассмотренной ранее функции <code>vector()</code>: | ||
+ | |||
+ | {{r-code|code=<nowiki>l <- vector("list", 10) | ||
+ | </nowiki>}} | ||
+ | |||
+ | === Матрицы === | ||
+ | |||
+ | Матрицы создаются с помощью соответствующей функции <code>matrix()</code>. Для создания матрицы необходимой размера, нам нужно указать количество строк и столбцов. Пример создания матрицы: | ||
+ | |||
+ | {{r-code|code=<nowiki>m <- matrix(NA, nrow = 100, ncol = 10) | ||
+ | </nowiki>}} | ||
+ | |||
+ | Поскольку матрица является также массивом, то матрицу можно также создать с помощью функции <code>array()</code>. Например: | ||
+ | |||
+ | {{r-code|code=<nowiki>m <- array(NA, dim = c(100, 10)) | ||
+ | </nowiki>}} | ||
+ | |||
+ | Переменные, полученные с помощью функций <code>matrix()</code> и <code>array()</code> будут идентичными. Убедиться в этом можно с помощью функции <code>identical()</code>: | ||
+ | |||
+ | {{r-code|code=<nowiki>identical(matrix(NA, nrow = 100, ncol = 10), | ||
+ | array(NA, dim = c(100, 10))) | ||
+ | #> [1] TRUE | ||
+ | </nowiki>}} | ||
+ | |||
+ | Матрицы и массивы можно также получить путём преобразования векторов или списков. Для этого необходимо изменить атрибут объекта, в котом хранится информация о размерности объекта. Получиться информацию о размерности объекта можно с помощью функции <code>dim()</code>. Данная функция также позволяет изменять размерность объекта. Приведём примеры: | ||
+ | |||
+ | {{r-code|code=<nowiki>m <- array(NA, dim = c(3, 2)) # создаём двухмерный массив с 3 строками и 2 столбцами | ||
+ | m | ||
+ | #> [,1] [,2] | ||
+ | #> [1,] NA NA | ||
+ | #> [2,] NA NA | ||
+ | #> [3,] NA NA | ||
+ | dim(m) | ||
+ | #> [1] 3 2 | ||
+ | dim(m) <- c(2, 3) # изменяем количество строк и столбцов | ||
+ | m | ||
+ | #> [,1] [,2] [,3] | ||
+ | #> [1,] NA NA NA | ||
+ | #> [2,] NA NA NA | ||
+ | dim(m) | ||
+ | #> [1] 2 3 | ||
+ | </nowiki>}} | ||
+ | |||
+ | Теперь мы может преобразовать вектор в матрицы путём присвоения вектору нужной нам размерности: | ||
+ | |||
+ | {{r-code|code=<nowiki>m <- rep(NA, 1000) | ||
+ | dim(m) <- c(100, 10) | ||
+ | </nowiki>}} | ||
+ | |||
+ | Обратим внимание на то, что количество элементов в векторе и массиве должно быть одинаковым, в противном случае R выдаст ошибку. Результат данного преобразования будут также идентичен предыдущим примерам: | ||
+ | |||
+ | {{r-code|code=<nowiki>m1 <- matrix(NA, nrow = 100, ncol = 10) | ||
+ | m2 <- rep(NA, 1000) | ||
+ | dim(m2) <- c(100, 10) | ||
+ | identical(m1, m2) | ||
+ | #> [1] TRUE | ||
+ | </nowiki>}} | ||
+ | |||
+ | === Таблицы данных === | ||
+ | |||
+ | Таблицы данных (<code>data.frame</code>) могут могу быть созданы путём объединения векторов, содержащих требуемые типы данных (см. [[{{FULLPAGENAME}}#Векторы| выше о создании векторов]]): | ||
+ | |||
+ | {{r-code|code=<nowiki>d <- data.frame(A = integer(100), | ||
+ | B = character(100), | ||
+ | C = double(100), | ||
+ | D = double(100), | ||
+ | E = integer(100), | ||
+ | stringsAsFactors = FALSE) | ||
+ | </nowiki>}} | ||
+ | |||
+ | == Примечания == | ||
+ | |||
+ | <references /> | ||
+ | |||
+ | [[Категория:R]] | ||
+ | [[Категория:Оптимизация кода]] |
Текущая версия на 17:45, 28 мая 2014
|
Материал «R:Оптимизация/Предварительное выделение памяти», созданный автором Артём Клевцов, публикуется на условиях лицензии Creative Commons «Attribution» («Атрибуция») 4.0 Всемирная. | |
|
Перед использованием функций из пакетов их необходимо предварительно установить и загрузить: КодR <syntaxhighlight lang="r">> install.packages(pkgs = "pkgname") > library(package = "pkgname")</syntaxhighlight> |
Частой задачей, решаемой с помощью циклов, является выполнение расчётов и занесение результатов в переменную. Таким образом, результирующая переменная будет заполняться данными по мере работы цикла. Предварительное выделение памяти (preallocate) позволяет ускорить работу циклов, работающих с постепенной заполняемыми данными. Суть данного метода заключается в том, чтобы заранее выделить место в оперативной памяти, в которую будут записываться данные во время работы цикла. Выделение памяти осуществляется путём указания типа и размера переменной. Если этого не сделать, то при каждой новой итерации необходимо выделять новое место в памяти и производить туда запись.
Обратите внимание, что переменные, участвующие в цикле, должны быть объявлены до того, как будут использоваться.
<syntaxhighlight lang="r">noaaloc <- function(n) { x <- NULL # объявляем пустую переменную for (i in seq_len(n)) x[i] <- i * i x } alloc <- function(n) { x <- integer(n) # объявляем переменную нужного типа и размера for (i in seq_len(n)) x[i] <- i * i x } </syntaxhighlight>
Теперь срвним время выполнения объявленных функций:
<syntaxhighlight lang="r">microbenchmark(noaaloc(10^4), alloc(10^4)) #> Unit: milliseconds #> expr min lq median uq max neval #> noaaloc(10^4) 38.545 39.596 39.977 40.595 78.476 100 #> alloc(10^4) 5.546 5.843 6.112 6.443 7.593 100 </syntaxhighlight>
Содержание
Создание пустых объектов в R
Векторы
integer(n) |
создаёт объект типа integer (число с фиксированной запятой) длинной n .
|
numeric(n) |
создаёт объект типа double (число с плавающей запятой) длинной n [1].
|
double(n) |
создаёт объект типа double (число с плавающей запятой) длинной n (число двойной точности).
|
single(n) |
создаёт объект типа double (число с плавающей запятой) длинной n (число одинарной точности).
|
complex(n) |
создаёт объект типа complex (комплексный тип данных) длинной n .
|
character(n) |
создаёт объект типа character (строковый тип данных) длинной n .
|
logical(n) |
создаёт объект типа logical (логический тип данных) длинной n .
|
Создание любого типа вектора можно также осуществить с помощью функции vector()
. Данная функция принимает два аргумента: mode
, указывающая тип данных и length
, указывающая длину вектора. Например, создание вектора целых чисел, длиной 100 можно создать с помощью следующих команд:
<syntaxhighlight lang="r">x <- integer(100) x <- vector("integer", 100) </syntaxhighlight>
Списки
Списки можно создавать с помощью уже рассмотренной ранее функции vector()
:
<syntaxhighlight lang="r">l <- vector("list", 10) </syntaxhighlight>
Матрицы
Матрицы создаются с помощью соответствующей функции matrix()
. Для создания матрицы необходимой размера, нам нужно указать количество строк и столбцов. Пример создания матрицы:
<syntaxhighlight lang="r">m <- matrix(NA, nrow = 100, ncol = 10) </syntaxhighlight>
Поскольку матрица является также массивом, то матрицу можно также создать с помощью функции array()
. Например:
<syntaxhighlight lang="r">m <- array(NA, dim = c(100, 10)) </syntaxhighlight>
Переменные, полученные с помощью функций matrix()
и array()
будут идентичными. Убедиться в этом можно с помощью функции identical()
:
<syntaxhighlight lang="r">identical(matrix(NA, nrow = 100, ncol = 10), array(NA, dim = c(100, 10))) #> [1] TRUE </syntaxhighlight>
Матрицы и массивы можно также получить путём преобразования векторов или списков. Для этого необходимо изменить атрибут объекта, в котом хранится информация о размерности объекта. Получиться информацию о размерности объекта можно с помощью функции dim()
. Данная функция также позволяет изменять размерность объекта. Приведём примеры:
<syntaxhighlight lang="r">m <- array(NA, dim = c(3, 2)) # создаём двухмерный массив с 3 строками и 2 столбцами m #> [,1] [,2] #> [1,] NA NA #> [2,] NA NA #> [3,] NA NA dim(m) #> [1] 3 2 dim(m) <- c(2, 3) # изменяем количество строк и столбцов m #> [,1] [,2] [,3] #> [1,] NA NA NA #> [2,] NA NA NA dim(m) #> [1] 2 3 </syntaxhighlight>
Теперь мы может преобразовать вектор в матрицы путём присвоения вектору нужной нам размерности:
<syntaxhighlight lang="r">m <- rep(NA, 1000) dim(m) <- c(100, 10) </syntaxhighlight>
Обратим внимание на то, что количество элементов в векторе и массиве должно быть одинаковым, в противном случае R выдаст ошибку. Результат данного преобразования будут также идентичен предыдущим примерам:
<syntaxhighlight lang="r">m1 <- matrix(NA, nrow = 100, ncol = 10) m2 <- rep(NA, 1000) dim(m2) <- c(100, 10) identical(m1, m2) #> [1] TRUE </syntaxhighlight>
Таблицы данных
Таблицы данных (data.frame
) могут могу быть созданы путём объединения векторов, содержащих требуемые типы данных (см. выше о создании векторов):
<syntaxhighlight lang="r">d <- data.frame(A = integer(100), B = character(100), C = double(100), D = double(100), E = integer(100), stringsAsFactors = FALSE) </syntaxhighlight>
Примечания
- ↑ Эквивалент функции
double()