2013-08-27 10 views
21

के साथ मैट्रिक्स का समान स्मृति उपयोग जब मैंने कुछ अजीब देखा तो मुझे आर में मैट्रिक्स के स्मृति उपयोग में रूचि थी। एक लूप में, मैंने प्रत्येक चरण, ऑब्जेक्ट आकार के लिए मैट्रिक्स के कॉलम की संख्या बढ़ा दी है और गणना की है।विभिन्न आकार

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

मेरी परिणाम

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

enter image description here

ऐसा नहीं है कि 2 पंक्तियाँ और 5,6,7 या 8 कॉलम के साथ एक मैट्रिक्स एक ही स्मृति का उपयोग करता है लगता है साजिश रची। हम उसे कैसे समझा सकते हैं?

+2

गु matrices से संबंधित नहीं है (जो आर वैसे भी वेक्टर हैं)। 'आकार <- प्रतिनिधि (NA_integer_, 100) देखें; के लिए (मैं 1: 100 में) आकार [i] <- object.size (प्रतिनिधि (1, i)); साजिश (आकार) '। – Roland

+1

चरित्र 'एम <- मैट्रिक्स (' ए ', 2, i)' और पूर्णांक 'एम <- मैट्रिक्स (1 एल, 2, i)' और 'm <- मैट्रिक्स (TRUE, 2, i) पर एक नज़र डालें - या अधिक रोचक रूप से @ रोलैंड ने सुझाव दिया (चरित्र, पूर्णांक और तार्किक वैक्टर के लिए)। – mnel

+0

@ साइमन ओ 101 हैडली ने इसे चैट में समझाया। मुझे आशा है कि उसे उचित उत्तर लिखने का समय मिल जाएगा। उदाहरण के लिए, [इस अनुभाग को आर-एक्सट्स में पढ़ें] (http://cran.r-project.org/doc/manuals/R-exts.html#Profiling-R-code-for-memory-use)। – Roland

उत्तर

35

को समझने के लिए यहाँ क्या हो रहा है, तो आप, आर में वस्तुओं हर वस्तु, कोई डेटा के साथ भी एक वस्तु के साथ जुड़े स्मृति भूमि के ऊपर के बारे में थोड़ा जानने की जरूरत के 40 बाइट्स है इसके साथ जुड़े डेटा:

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

यह स्मृति वस्तु के प्रकार के स्टोर करने के लिए (के रूप में typeof() द्वारा दिया) प्रयोग किया जाता है, और अन्य मेटाडाटा स्मृति प्रबंधन के लिए की जरूरत है।

इस ओवरहेड को अनदेखा करने के बाद, आप उम्मीद कर सकते हैं कि वेक्टर की स्मृति उपयोग वेक्टर की लंबाई के समान है।

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

यह स्मृति के उपयोग की तरह दिखता है मोटे तौर पर वेक्टर की लंबाई के लिए आनुपातिक है, लेकिन वहाँ 168 बाइट्स और छोटे discontinuities पर एक बड़ा अलगाव हर है: चलो भूखंडों के एक जोड़े के साथ कि बाहर की जाँच करते हैं कुछ कदम। बड़ी असंतोष इसलिए है क्योंकि आर में वैक्टर के लिए दो स्टोरेज पूल हैं: ओएस द्वारा प्रबंधित छोटे वैक्टर, और बड़े वैक्टर, यह एक प्रदर्शन अनुकूलन है क्योंकि स्मृति की बहुत सारी मात्रा आवंटित करना महंगा है)।

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 से कदम बड़ा कारण बनता है: छोटे वैक्टर केवल 8, 16, 32, 48, 64 या 128 बाइट्स लंबे, एक बार हम 40 बाइट ओवरहेड को दूर जो हो सकता है, हम देखते हैं ठीक है

# 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 
: कदम है, तो एक बार हम बड़े वेक्टर पूल में पार कर लिया है, वैक्टर 8 बाइट (स्मृति एक निश्चित आकार की इकाइयों में आता है, और आर आधे से एक इकाई के लिए नहीं पूछ सकते हैं) की मात्रा में आवंटित किए जाते हैं

तो यह व्यवहार मैट्रिस के साथ आप जो देखते हैं उससे मेल खाता है? ठीक है, पहले हम एक मैट्रिक्स के साथ जुड़े भूमि के ऊपर से देखने की जरूरत है:

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

object.size(xm) 
# 200 bytes 

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

तो एक मैट्रिक्स भंडारण की एक अतिरिक्त 160 बाइट्स की जरूरत है एक सदिश की तुलना में। 160 बाइट क्यों?क्योंकि एक मैट्रिक्स दो पूर्णांकों युक्त एक dim विशेषता है यह, और विशेषताओं एक pairlist (list() के एक पुराने संस्करण) में जमा हो जाती है:

object.size(pairlist(dims = c(1L, 1L))) 
# 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") 

Memory usage of matrices

+5

+1 दिलचस्प और महान जवाब। धन्यवाद हैडली –

+1

धन्यवाद हैडली। यह एक सही जवाब है। – Bangyou

7

ऐसा लगता है कि छोटे छोर पर कॉलम की एक बहुत ही विशिष्ट श्रृंखला के लिए होता है। 1-100 कॉलम के साथ मैट्रिक्स को देखते हुए मैं निम्न देखें:

enter image description here

मैं किसी अन्य पठारों नहीं दिख रहा है, भले ही मैं कॉलम कहने के लिए की संख्या में वृद्धि, 10000:

enter image description here

Intrigued, मैं थोड़ा आगे देखा है, एक समारोह में अपने कोड डाल:, हम सेंट दिलचस्प बात यह है

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 
} 

बीमार इस पठार और कम संख्या में सीधी रेखा को देखने अगर हम पठार सिकुड़ने और पीछे की ओर ले जाने वाले पंक्तियों की संख्या बढ़ाने के लिए, अंत में समय हम nrow=8 मारा द्वारा एक सीधी रेखा को समायोजित करने से पहले:

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

का संकेत यह एक मैट्रिक्स में कोशिकाओं की संख्या के लिए एक बहुत ही विशिष्ट सीमा के लिए होता है; 9-16।

मेमोरी आवंटन

रूप @Hadley उसकी टिप्पणी में बताया, वहाँ एक समान thread on memory allocation of vectors है। जो फॉर्मूला के साथ आता है: 40 + 8 * floor(n/2)numeric आकार n के वैक्टर।

मैट्रिस के लिए ओवरहेड थोड़ा अलग है, और स्टेपिंग रिलेशनशिप नहीं है (जैसा कि मेरे भूखंडों में देखा गया है)। इसके बजाय मैं सूत्र 208 + 8 * n बाइट्स जहां n, मैट्रिक्स (nrow * ncol) में कोशिकाओं की संख्या है को छोड़कर जहां n है के साथ आए हैं 9 और 16 के बीच: आकार

मैट्रिक्स - "double" मेट्रिसेस, 1 पंक्ति, 1 के लिए 208 बाइट्स -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 

हाउवर।हम पूर्णांक या तार्किक करने के लिए मैट्रिक्स के प्रकार बदलते हैं, तो हम स्मृति आवंटन में चरणबद्ध व्यवहार ऊपर सूत्र में वर्णित देख पा रहे हैं:

मैट्रिक्स आकार - "integer" मैट्रिक्स 1 पंक्ति, 1-20 स्तंभों के लिए 208 बाइट्स:

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

यह आश्चर्य की बात है कि हम प्रकार double के एक मैट्रिक्स के साथ समान व्यवहार नहीं दिख रहा है, के रूप में यह साथ सिर्फ एक "numeric" वेक्टर है एक dim विशेषता संलग्न (R lang specification)।

स्मृति आवंटन में हम जो बड़ा कदम देखते हैं, वह R से आता है जिसमें दो मेमोरी पूल होते हैं, एक छोटे वैक्टर के लिए और एक बड़े वैक्टर के लिए, और ऐसा होता है जहां कूद बनती है। हैडली विकम ने अपनी प्रतिक्रिया में विस्तार से बताया।

5

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

enter image description here

+0

हां, यह इसमें खुदाई करने का एक बहुत चालाक तरीका है! –

संबंधित मुद्दे