una suma online multiplicacion matriz matrices inversa incognitas hallar determinante con calculadora r memory matrix size

suma - multiplicacion de matrices online



El mismo uso de memoria de matrices con diferente tamaƱo (3)

Esta pregunta ya tiene una respuesta aquí:

Estaba interesado en el uso de la memoria de las matrices en R cuando observé algo extraño. En un bucle, hice crecer el número de columnas de una matriz y calculé, para cada paso, el tamaño del objeto como este:

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

Lo que da

plot(size[,1], size[,2], xlab="n columns", ylab="memory")

Parece que las matrices con 2 filas y 5, 6, 7 u 8 columnas usan exactamente la misma memoria. ¿Cómo podemos explicar eso?


Esto parece suceder solo para un rango muy específico de columnas en el extremo más pequeño. En cuanto a las matrices con 1-100 columnas veo lo siguiente:

No veo ninguna otra meseta, incluso si aumento la cantidad de columnas para decir, 10000:

Intrigado, he analizado un poco más, poniendo tu código en una función:

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 }

Curiosamente, todavía vemos esta meseta y una línea recta en números bajos si aumentamos el número de filas, con la meseta contrayéndose y moviéndose hacia atrás, antes de ajustar finalmente a una línea recta cuando tocamos nrow=8 :

Indicando que esto ocurre en un rango muy específico para la cantidad de celdas en una matriz; 9-16.

Asignación de memoria

Como señaló @Hadley en su comentario, hay un hilo similar en la asignación de memoria de los vectores . Que viene con la fórmula: 40 + 8 * floor(n / 2) para vectores numeric de tamaño n .

Para las matrices, la sobrecarga es ligeramente diferente, y la relación de pasos no se mantiene (como se ve en mis gráficos). En su lugar, he encontrado la fórmula 208 + 8 * n bytes donde n es el número de celdas en la matriz ( nrow * ncol ), excepto donde n está entre 9 y 16:

Tamaño de la matriz: 208 bytes para matrices "double" , 1 fila, 1-20 columnas:

> 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

SIN EMBARGO. Si cambiamos el tipo de la matriz a Entero o Lógico, vemos el comportamiento gradual en la asignación de memoria que se describe en el hilo anterior:

Tamaño de la matriz: 208 bytes para matrices "integer" 1 fila, 1-20 columnas:

> 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

De manera similar para "logical" matrices "logical" :

> 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

Es sorprendente que no veamos el mismo comportamiento con una matriz de tipo double , ya que es solo un vector "numeric" con un atributo dim adjunto ( especificación R lang ).

El gran paso que vemos en la asignación de memoria proviene de que R tiene dos grupos de memoria, uno para vectores pequeños y otro para vectores grandes, y que es donde se realiza el salto. Hadley Wickham explica esto en detalle en su respuesta.


Mira el vector numérico con un tamaño del 1 al 20, obtuve esta figura.

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])


Para entender qué está pasando aquí, necesita saber un poco sobre la sobrecarga de memoria asociada a los objetos en R. Todos los objetos, incluso los que no tienen datos, tienen 40 bytes de datos asociados:

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

Esta memoria se usa para almacenar el tipo de objeto (como lo devuelve typeof() ) y otros metadatos necesarios para la gestión de la memoria.

Después de ignorar esta sobrecarga, es de esperar que el uso de memoria de un vector sea proporcional a la longitud del vector. Veamos eso con un par de tramas:

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

Parece que el uso de memoria es más o menos proporcional a la longitud del vector, pero hay una gran discontinuidad en 168 bytes y pequeñas discontinuidades cada pocos pasos. La gran discontinuidad se debe a que R tiene dos pools de almacenamiento para vectores: vectores pequeños, administrados por R, y vectores grandes, administrados por el sistema operativo (Esto es una optimización del rendimiento porque la asignación de muchas cantidades pequeñas de memoria es costosa). Los vectores pequeños solo pueden tener 8, 16, 32, 48, 64 o 128 bytes de longitud, lo que una vez que eliminamos los 40 bytes de sobrecarga, es exactamente lo que vemos:

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

El paso de 64 a 128 causa el gran paso, luego, una vez que hemos cruzado al gran conjunto de vectores, los vectores se asignan en trozos de 8 bytes (la memoria viene en unidades de un cierto tamaño, y R no puede pedir la mitad unidad):

# 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

Entonces, ¿cómo se corresponde este comportamiento con lo que se ve con las matrices? Bueno, primero tenemos que mirar la sobrecarga asociada a una matriz:

xv <- numeric() xm <- matrix(xv) object.size(xm) # 200 bytes object.size(xm) - object.size(xv) # 160 bytes

Por lo tanto, una matriz necesita 160 bytes adicionales de almacenamiento en comparación con un vector. ¿Por qué 160 bytes? Es porque una matriz tiene un atributo dim contiene dos enteros, y los atributos se almacenan en una pairlist (una versión anterior de list() ):

object.size(pairlist(dims = c(1L, 1L))) # 160 bytes

Si volvemos a dibujar la gráfica anterior usando matrices en lugar de vectores, y aumentamos todas las constantes en el eje y en 160, se puede ver que la discontinuidad corresponde exactamente al salto del grupo de vectores pequeños al grupo de vectores grandes:

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")