Как избежать выделения памяти с помощью вычислений линейной алгебры в R - PullRequest
1 голос
/ 23 мая 2019

В качестве тривиального примера, скажем, мне интересно вычислить:

r = v*M^t

Где r и v - векторы, а M - чрезвычайно большая разреженная матрица.

Я могу решить это одним из двух способов:

r = v*(M*M*M*M...)
r = ((((v*M)M)M)M)...

Там, где первый подход приводит к получению промежуточных плотных матриц, которые нецелесообразно хранить в ОЗУ (для моего целевого минимального варианта использования мне понадобится как минимум 10 терабайт). Второе решение, напротив, всегда приводит к промежуточным векторам, и на самом деле оно работает на практике.

Проблема заключается в том, что при больших значениях t выделение памяти вызывает существенное узкое место в производительности.

library(pryr)

n = 20000

v = 1:n

M = matrix(1:(n*n), n) # Not a sparse matrix like my use case, but easier to start with

for (i in 1:10) {
  v = v %*% M
  print(address(v))
}

Как показывает функция address (), v перераспределяется при каждой итерации. Он не изменяется на месте. Распределение памяти не только замедляет работу, но, согласно profvis, сборщик мусора также постоянно вызывается и занимает большую часть времени.

Итак, мой вопрос: есть ли способ выполнить это вычисление (и, возможно, другие подобные ему) в R без лишних выделений памяти и вызовов gc (), происходящих под капотом?

...