Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 不同大小矩阵的相同内存使用_R_Memory_Matrix_Size - Fatal编程技术网

R 不同大小矩阵的相同内存使用

R 不同大小矩阵的相同内存使用,r,memory,matrix,size,R,Memory,Matrix,Size,当我观察到一些奇怪的事情时,我对R中矩阵的记忆使用很感兴趣。在一个循环中,我使矩阵的列数增长,并计算每个步骤的对象大小,如下所示: x <- 10 size <- matrix(1:x, x, 2) for (i in 1:x){ m <- matrix(1, 2, i) size[i,2] <- object.size(m) } 似乎具有2行和5、6、7或8列的矩阵使用完全相同的内存。我们如何解释呢?这似乎只发生在小端的特定列范围内。查看包含1-100列

当我观察到一些奇怪的事情时,我对R中矩阵的记忆使用很感兴趣。在一个循环中,我使矩阵的列数增长,并计算每个步骤的对象大小,如下所示:

x <- 10
size <- matrix(1:x, x, 2)

for (i in 1:x){
  m  <- matrix(1, 2, i)
  size[i,2] <- object.size(m)
}


似乎具有2行和5、6、7或8列的矩阵使用完全相同的内存。我们如何解释呢?

这似乎只发生在小端的特定列范围内。查看包含1-100列的矩阵,我看到以下内容:

我没有看到任何其他高原,即使我增加了列数,比如10000:

有趣的是,我进一步研究了,将代码放入函数中:

sizes <- function(nrow, ncol) {
  size=matrix(1:ncol,ncol,2)
  for (i in c(1:ncol)){
    m = matrix(1,nrow, i)
    size[i,2]=object.size(m)
  } 
  plot(size[,1], size[,2])
  size
}
不过。如果我们将矩阵的类型更改为整数或逻辑,我们确实可以看到上面线程中描述的内存分配的逐步行为:

矩阵大小-208字节用于
“整数”
矩阵1行1-20列:

> sapply(1:20, function(x) { object.size(matrix(1, 1, x)) })-208
 [1]   0   8  24  24  40  40  56  56 120 120 120 120 120 120 120 120 128 136 144
[20] 152
> sapply(1:20, function(x) { object.size(matrix(1L, 1, x)) })-208
 [1]   0   0   8   8  24  24  24  24  40  40  40  40  56  56  56  56 120 120 120
[20] 120
类似地,对于
“逻辑”
矩阵:

> sapply(1:20, function(x) { object.size(matrix(1L, 1, x)) })-208
 [1]   0   0   8   8  24  24  24  24  40  40  40  40  56  56  56  56 120 120 120
[20] 120
令人惊讶的是,对于类型为
double
的矩阵,我们没有看到相同的行为,因为它只是一个
带有
dim
属性的
数值向量()


我们在内存分配中看到的一大步来自于
R
有两个内存池,一个用于小向量,一个用于大向量,而这恰好是跳转的地方。Hadley Wickham在他的回答中详细解释了这一点。

看看大小从1到20的数字向量,我得到了这个数字

x=20
size=matrix(1:x,x,2)
for (i in c(1:x)){
   m = rep(1, i)
   size[i,2]=object.size(m)
}

plot(size[,1],size[,2])

要了解这里的情况,您需要了解一点与R中的对象相关联的内存开销。每个对象,即使是没有数据的对象,都有40字节的数据与之相关:

x0 <- numeric()
object.size(x0)
# 40 bytes

看起来内存使用量大致与向量的长度成正比,但在168字节处有一个大的不连续性,每隔几步就有一个小的不连续性。最大的不连续性是因为R有两个向量存储池:由R管理的小向量和由OS管理的大向量(这是一个性能优化,因为分配大量的少量内存非常昂贵)。小向量只能是8、16、32、48、64或128字节长,一旦我们去掉40字节的开销,这正是我们看到的:

sizes - 40
#  [1]   0   8   8  16  16  32  32  32  32  48  48  48  48  64  64  64  64 128 128 128 128
# [22] 128 128 128 128 128 128 128 128 128 128 128 128 136 136 144 144 152 152 160 160 168
# [43] 168 176 176 184 184 192 192 200 200
从64到128的步骤导致了一个大的步骤,然后一旦我们进入了大向量池,向量被分配成8字节的块(内存是以一定大小的单位来分配的,R不能要求半个单位):

那么,这种行为是如何与你所看到的矩阵相对应的呢?首先,我们需要看看与矩阵相关的开销:

xv <- numeric()
xm <- matrix(xv)

object.size(xm)
# 200 bytes

object.size(xm) - object.size(xv)
# 160 bytes
如果我们使用矩阵而不是向量重新绘制上一个图,并将y轴上的所有常数增加160,您可以看到不连续性正好对应于从小向量池到大向量池的跳跃:

msizes <- sapply(0:50, function(n) object.size(as.matrix(seq_len(n))))
plot(c(0, 50), c(160, max(msizes)), xlab = "Length", ylab = "Bytes", 
  type = "n")
abline(h = 40 + 160, col = "grey80")
abline(h = 40 + 160 + 128, col = "grey80")
abline(a = 40 + 160, b = 4, col = "grey90", lwd = 4)
lines(msizes, type = "s")

msizes这与矩阵无关(反正它们是R中的向量)。看看
大小看看character
m@SimonO101哈德利在聊天中解释了这一点。我希望他有时间写一个恰当的答案。例如,阅读。@Roland谢谢,我只是很有趣。哈,这是一个更聪明的挖掘方法+一个有趣而伟大的答案。谢谢哈德利谢谢哈德利。这是一个完美的答案。
# diff(sizes)
#  [1]  8  0  8  0 16  0  0  0 16  0  0  0 16  0  0  0 64  0  0  0  0  0  0  0  0  0  0  0
# [29]  0  0  0  0  8  0  8  0  8  0  8  0  8  0  8  0  8  0  8  0  8  0
xv <- numeric()
xm <- matrix(xv)

object.size(xm)
# 200 bytes

object.size(xm) - object.size(xv)
# 160 bytes
object.size(pairlist(dims = c(1L, 1L)))
# 160 bytes
msizes <- sapply(0:50, function(n) object.size(as.matrix(seq_len(n))))
plot(c(0, 50), c(160, max(msizes)), xlab = "Length", ylab = "Bytes", 
  type = "n")
abline(h = 40 + 160, col = "grey80")
abline(h = 40 + 160 + 128, col = "grey80")
abline(a = 40 + 160, b = 4, col = "grey90", lwd = 4)
lines(msizes, type = "s")