Как ускорить запись в матрицу в справочном классе в R - PullRequest
1 голос
/ 25 июня 2019

Вот фрагмент кода R, который записывает каждый элемент матрицы в ссылочном классе.Он работает невероятно медленно, и мне интересно, если я пропустил простой трюк, который ускорит это.

nx = 2000
ny = 10
ref_matrix <- setRefClass(
   "ref_matrix",fields = list(data  = "matrix"),
)
out <- ref_matrix(data = matrix(0.0,nx,ny))
#tracemem(out$data)
for (iy in 1:ny) {
   for (ix in 1:nx) {
      out$data[ix,iy] <- ix + iy
   }
}

Кажется, что каждая запись в элемент матрицы запускает проверку, которая включает в себякопия всей матрицы.(Раскомментирование вызова tracemen () показывает это.) Теперь я нашел обсуждение, которое, кажется, подтверждает это: https://r -devel.r-project.narkive.com / 8KtYICjV / rd-copy-on-присваивание большому полю эталонного класса , и это также, по-видимому, охватывается ускорением доступа к полям в эталонных классах R , но в обоих случаях это поведение можно обойти, если необъявление класса для поля, и это работает для примера в первой ссылке, который использует одномерный вектор b, который можно просто установить как b << - 1: 10000.Но я не нашел эквивалентного способа создания 2D-массива без использования явного «матричного» экземпляра. </p>

Я просто что-то упустил, или это на самом деле невозможно?

Позвольте мне добавить пару вещей.Во-первых, я очень плохо знаком с R, поэтому мог легко что-то пропустить.Во-вторых, мне просто любопытно, как справочные классы работают в этом случае и существует ли простой способ их эффективного использования;Я не ищу действительно быстрого способа установки элементов матрицы - я могу сделать это, вообще не имея матрицы в ссылочном классе, и если я действительно беспокоюсь о скорости, я могу написать подпрограмму C, чтобы сделать этои назовите это от R.

Вот некоторая справка, которая может объяснить, почему я заинтересован в этом, которую вы можете игнорировать.

Я пришел сюда, желая увидеть, как разные языкии даже разные параметры компилятора и разные способы кодирования одной и той же операции по сравнению с эффективностью при доступе к двумерным прямоугольным массивам.Я играл с тестовой программой, которая создает два двумерных массива одинакового размера и вызывает подпрограмму, которая устанавливает первый для элементов второго плюс их значения индекса.(Практически любая операция подойдет, но эта операция не совсем тривиальна для оптимизации.) Сейчас у меня есть это на нескольких языках, C, C ++, Julia, Tcl, Fortran, Swift и т. Д., Даже на ассемблере, написанном вручную (предупреждение о спойлере: ассемблер больше не стоит усилий) и подумал, что я попробую R. Очевидная реализация в R передает два массива подпрограмме, которая выполняет работу, но поскольку R обычно не передается по ссылке, этоПодпрограмма должна сделать копию измененного массива и вернуть ее в качестве значения функции.Я подумал, что использование ссылочного класса позволит избежать сравнительно небольших накладных расходов на эту копию, поэтому я попробовал это и с удивлением обнаружил, что это не только ускоряет процесс, но и сильно замедляет его.

1 Ответ

1 голос
/ 25 июня 2019

Использование outer:

out$data <- outer(1:ny, 1:nx, `+`)

Кроме того, не используйте ссылочные классы (или классы R6), если вам не нужна ссылочная семантика. ПОЦЕЛУЙ и все такое.

...