производительность фрейма (матрицы) данных: расположение памяти - PullRequest
3 голосов
/ 19 января 2011

Я новичок в R. Предположим, что структура памяти одинакова для фрейма данных и матрицы.

В следующей матрице

а = матрица (1: 10000000,1000000,10) * * 1 006

имеет 1М строк и 10 столбцов. Память для строки или для столбца физически последовательна? Или физическая память сначала хранит [1,1], [2,1], [3,1] ,, [1M, 1], [2,1] или [1,2], [1,2], .. [1,10], [2,1] ...

Предположим, что матрица с элементом 10M имеет размер 100M, а кэш-память L2 равна 4M, тогда кэш-память L2 не может хранить все эти элементы 10M. Если мы обработаем данные последовательно, у нас будет меньшее количество пропущенных кэшей L2. В нашем случае нам нужно обрабатывать строку за строкой и читать несколько столбцов одновременно, например столбцы A, B, C, а затем создать какой-то результат. Если в памяти сначала хранятся 10 элементов в 1-м ряду, а затем 10 элементов во 2-м ряду, производительность может быть выше.

Есть ли способ управления макетом памяти?

Ответы [ 2 ]

6 голосов
/ 19 января 2011

Матрицы хранятся по столбцам:

> m=matrix(1:12,nrow=3)
> m
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12

Фреймы данных - это просто симпатичные списки, а списки хранятся как векторы элементов.Я даже не уверен, что элементы списка гарантированно будут смежными в памяти.

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

2 голосов
/ 19 января 2011

Матрица - это просто вектор с атрибутом dim. Элементы матрицы хранятся в векторе в главном порядке столбцов. Нет способа изменить это.

Поэтому, если вам нужно работать строка за строкой, быстрее переставить матрицу перед ее циклическим циклом.

> set.seed(21)
> a = matrix(rnorm(1e6),1e3,1e3)
> ta = t(a)
> system.time(for(i in 1:1000) colSums(ta))
   user  system elapsed 
   1.39    0.00    1.40 
> system.time(for(i in 1:1000) rowSums(a))
   user  system elapsed 
   2.40    0.00    2.39 
> identical(rowSums(a), colSums(ta))
[1] TRUE

Если вы хотите копать глубже, код для colSums, rowSums, colMeans и rowMeans находится в функции do_colsum в src/main/array.c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...