2013-08-27 18 views
21

Garip bir şey gözlemlediğimde R'deki matrisin bellek kullanımıyla ilgileniyordum. Bir döngüde, bir matrisin sütun sayısını artırdım ve her adım için nesne boyutunu hesapladım.Farklı boyuttaki matrisle aynı bellek kullanımı

x=10 
size=matrix(1:x,x,2) 

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

benim sonuç

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

enter image description here

2 adet satır ve 5,6,7 veya 8 sütunlu bir matris aynı bellek kullanan görünüyor Çizilen. Bunu nasıl açıklayabiliriz?

+2

Th: 160, y-ekseni üzerinde, tüm sabitler, sen süreksizlik büyük vektör havuzuna küçük vektör havuzundan atlama tam olarak karşılık görebilir Matrislerle ilişkili değildir (yine de R vektörleridir). Boyutlara bakın <- rep (NA_integer_, 100); (i: 1: 100) boyutlarında [i] <- object.size (rep (1, i)); arsa (boyut) '. – Roland

+1

Karaktere 'm <- matris (' a ', 2, i)' ve tamsayı 'm <- matrisi (1L, 2, i)' ve 'm <- matrisi (DOĞRU, 2, i)' karakterine bakınız. - ya da daha ilginç olanı @Roland'ın önerdiği (karakter, tamsayı ve mantıksal vektörler için). – mnel

+0

@ SimonO101 Hadley sohbette açıkladı. Umarım uygun bir cevap yazma zamanı bulur. E.g., [bu bölüm R-exts] 'ı okuyun (http://cran.r-project.org/doc/manuals/R-exts.html#Profiling-R-code-for-memory-use). – Roland

cevap

35

, sen 40 bayt olan, R. nesnelerin Her nesne, Verisiz bile bir nesne ile ilişkili bellek yükü hakkında biraz bilmek gerekir (typeof() tarafından döndürülen gibi) bu bellek nesnesi tipini saklamak için kullanılan

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

ve bellek yönetimi için gerekli diğer meta: onunla ilişkili verileri.

Bu ek yükü göz ardı ettikten sonra, bir vektörün bellek kullanımının vektörün uzunluğuyla orantılı olmasını bekleyebilirsiniz. Bu bellek kullanımı gibi görünüyor

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

Memory usage of vectors

vektörün uzunluğuna kabaca orantılıdır, ancak 168 byte ve küçük süreksizliklerinde büyük süreksizliği her vardır: en araziler bir çift ile bir kontrol edelim birkaç adım. Büyük süreksizlik, R'nin vektörler için iki depolama havuzuna sahip olmasından kaynaklanıyor: R tarafından yönetilen küçük vektörler ve işletim sistemi tarafından yönetilen büyük vektörler (Bu, bir performans optimizasyonu, çünkü çok az miktarda bellek ayırmak pahalıdır).

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 

128 64 den adım büyük nedenleri: Küçük vektörler sadece bir kez biz 40 bayt yükü kaldırmak hangi, 8, 16, 32, 48, 64 veya 128 bayt uzunluğunda olabilir, gördüğümüz tam olarak ne

# 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 
: Eskiden büyük vektör havuza geçtim bir kez adım, daha sonra, vektörler 8 bayt (bellek belirli bir boyuttaki birimlerinde gelir ve R yarım birim için sormak olamaz) parçaları tahsis edilir

Peki bu davranış matrislerle gördüğünüzle nasıl örtüşüyor? Öncelikle biz bir matris ile ilişkili ek yükü bakmak gerekir:

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

object.size(xm) 
# 200 bytes 

object.size(xm) - object.size(xv) 
# 160 bytes 

Yani bir matris bir vektör ile karşılaştırıldığında depolama fazladan 160 bayt ihtiyacı

. Neden 160 bayt?bir matris iki tamsayılar içeren bir dim niteliği vardır çünkü, ve nitelikleri bir pairlist ( list() eski bir sürümünü) saklanır:

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

önceki yerine vektörlerin matrisler kullanılarak arsa ve artış yeniden çizerseniz

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

Memory usage of matrices

+5

+1 ilginç ve harika bir cevap. Teşekkürler hadley –

+1

Teşekkürler hadley. Bu mükemmel bir cevap. – Bangyou

7

Bu, küçük uçta yalnızca çok özel bir sütun aralığı için geçerli gibi görünüyor. 10000, söyleyecek sütun sayısını artırmak bile

enter image description here

Ben başka yaylaları görmüyorum:

enter image description here

1-100 sütunlu matrislerin baktığımızda aşağıdaki bakın

, ben daha biraz baktım, Intrigued bir fonksiyonu kodunuzu koyarak: İlginç

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 
} 

, biz st hasta nihayet biz nrow=8 isabet zaman düz bir çizgiye ayarlamadan önce, plato sıkılması ve geriye doğru hareket ile, satır sayısı artarsa ​​düşük sayılarda bu platoya ve düz bir çizgi bkz: belirten

Size of matrices with 3-8 rows with 10 columns:

Bu, bir matristeki hücre sayısı için çok spesifik bir aralık için gerçekleşir; 9-16.

@Hadley yaptığı açıklamada belirttiği gibi Bellek Tahsisi

benzer thread on memory allocation of vectors yoktur. Hangi formülü ile gelir: numericn boyutundaki vektörler için 40 + 8 * floor(n/2).

Matrisler için ek yük biraz farklıdır ve adımlama ilişkisi (benim çizimlerimde görüldüğü gibi) beklemez. Bunun yerine nn olduğu durumlar hariç, bir matris (nrow * ncol) hücre sayısı olduğu formül 208 + 8 * n bayt ile geldi 9 ile 16:

Matris boyutu - "double" matrisler, 1 satır, 1 208 bayt -20 sütunlar: ŞEKİL 3.Biz tamsayı veya mantıksal matrisin türünü değiştirmek için, yukarıda iplik tarif edilen bellek ayırma aşamalı davranışı görüyoruz:

Matris boyutu - "integer" matrisler 1 satır 1-20 sütun için 208 bayt:

"logical" matrisleri için Benzer
> 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 

o sadece bir "numeric" vektörü olarak biz, tip double bir matris ile aynı davranışı görmüyorum olması şaşırtıcıdır Ekli dim özniteliği (R lang specification).

Bellek ayırmada gördüğümüz en büyük adım, iki bellek havuzuna sahip, biri küçük vektörler için ve bir tanesi Büyük vektörler için olan ve bu, atlama yapıldığı yerde olan R'dan gelir. Hadley Wickham bu cevabı ayrıntılı olarak açıklıyor.

5

1'den 20'ye kadar olan sayısal vektöre baktığımda, bu rakamı aldım. Burada ne olup bittiğini anlamak için

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

enter image description here

+0

Hah, bu içine girmenin çok zekice bir yolu! –