memory management - एक आर सत्र में उपलब्ध स्मृति का प्रबंधन करने के लिए चालें




memory-management (17)

  1. मैं सौभाग्यशाली हूं और मेरे बड़े डेटा सेट लगभग 100 एमबी (32 बिट बाइनरी) के "भाग" (सबसेट) में उपकरण द्वारा सहेजे गए हैं। इस प्रकार मैं डेटा सेट को फ़्यूज़ करने से पहले अनुक्रमिक रूप से प्री-प्रोसेसिंग चरणों (अनौपचारिक भागों को हटाने, डाउनसमैप्लिंग) कर सकता हूं।

  2. कॉलिंग gc () "हाथ से" मदद कर सकता है अगर डेटा का आकार उपलब्ध स्मृति के करीब हो।

  3. कभी-कभी एक अलग एल्गोरिदम को बहुत कम स्मृति की आवश्यकता होती है।
    कभी-कभी वेक्टरनाइज़ेशन और मेमोरी उपयोग के बीच एक व्यापार बंद होता है।
    तुलना करें: लूप के for split और lapply बनाम।

  4. तेज़ और आसान डेटा विश्लेषण के लिए, मैं अक्सर डेटा के एक छोटे से यादृच्छिक सबसेट ( sample () ) के साथ काम करता हूं। एक बार डेटा विश्लेषण स्क्रिप्ट / आरएनडब्ल्यू डेटा विश्लेषण कोड समाप्त हो गया है और पूरा डेटा गणना रात में / सप्ताहांत / ... गणना के लिए गणना सर्वर पर जाता है।

इंटरेक्टिव आर सत्र की उपलब्ध स्मृति को प्रबंधित करने के लिए लोग किस चाल का उपयोग करते हैं? मैं नीचे दिए गए कार्यों का उपयोग करता हूं [2004 में आर-हेल्प सूची में पेट्र पिकल और डेविड हिंड्स द्वारा पोस्टिंग के आधार पर) सबसे बड़ी वस्तुओं की सूची (और / या क्रमबद्ध) और मौलिक रूप से rm() कुछ को। लेकिन अब तक का सबसे प्रभावी समाधान ... 64-बिट लिनक्स के तहत पर्याप्त स्मृति के साथ चलाने के लिए था।

कोई अन्य अच्छी चाल लोग साझा करना चाहते हैं? प्रति पोस्ट एक, कृपया।

# improved list of objects
.ls.objects <- function (pos = 1, pattern, order.by,
                        decreasing=FALSE, head=FALSE, n=5) {
    napply <- function(names, fn) sapply(names, function(x)
                                         fn(get(x, pos = pos)))
    names <- ls(pos = pos, pattern = pattern)
    obj.class <- napply(names, function(x) as.character(class(x))[1])
    obj.mode <- napply(names, mode)
    obj.type <- ifelse(is.na(obj.class), obj.mode, obj.class)
    obj.size <- napply(names, object.size)
    obj.dim <- t(napply(names, function(x)
                        as.numeric(dim(x))[1:2]))
    vec <- is.na(obj.dim)[, 1] & (obj.type != "function")
    obj.dim[vec, 1] <- napply(names, length)[vec]
    out <- data.frame(obj.type, obj.size, obj.dim)
    names(out) <- c("Type", "Size", "Rows", "Columns")
    if (!missing(order.by))
        out <- out[order(out[[order.by]], decreasing=decreasing), ]
    if (head)
        out <- head(out, n)
    out
}
# shorthand
lsos <- function(..., n=10) {
    .ls.objects(..., order.by="Size", decreasing=TRUE, head=TRUE, n=n)
}

@ डिर्क और @ टोनी के जवाब के आधार पर मैंने थोड़ा सा अपडेट किया है। परिणाम सुंदर आकार मानों से पहले [1] आउटपुट कर रहा था, इसलिए मैंने कब्जा कर लिया। capture.output जिसने समस्या हल की:

.ls.objects <- function (pos = 1, pattern, order.by,
                     decreasing=FALSE, head=FALSE, n=5) {
napply <- function(names, fn) sapply(names, function(x)
    fn(get(x, pos = pos)))
names <- ls(pos = pos, pattern = pattern)
obj.class <- napply(names, function(x) as.character(class(x))[1])
obj.mode <- napply(names, mode)
obj.type <- ifelse(is.na(obj.class), obj.mode, obj.class)
obj.prettysize <- napply(names, function(x) {
    format(utils::object.size(x),  units = "auto") })
obj.size <- napply(names, utils::object.size)

obj.dim <- t(napply(names, function(x)
    as.numeric(dim(x))[1:2]))
vec <- is.na(obj.dim)[, 1] & (obj.type != "function")
obj.dim[vec, 1] <- napply(names, length)[vec]
out <- data.frame(obj.type, obj.size, obj.prettysize, obj.dim)
names(out) <- c("Type", "Size", "PrettySize", "Rows", "Columns")
if (!missing(order.by))
    out <- out[order(out[[order.by]], decreasing=decreasing), ]
if (head)
    out <- head(out, n)

return(out)
}

# shorthand
lsos <- function(..., n=10) {
    .ls.objects(..., order.by="Size", decreasing=TRUE, head=TRUE, n=n)
}

lsos()

इसे एक ट्विटर पोस्ट पर देखा और लगता है कि यह Dirk द्वारा एक अद्भुत काम है! जेडी लांग के जवाब से निम्नलिखित के बाद, मैं इसे उपयोगकर्ता के अनुकूल पढ़ने के लिए करता हूं:

# improved list of objects
.ls.objects <- function (pos = 1, pattern, order.by,
                        decreasing=FALSE, head=FALSE, n=5) {
    napply <- function(names, fn) sapply(names, function(x)
                                         fn(get(x, pos = pos)))
    names <- ls(pos = pos, pattern = pattern)
    obj.class <- napply(names, function(x) as.character(class(x))[1])
    obj.mode <- napply(names, mode)
    obj.type <- ifelse(is.na(obj.class), obj.mode, obj.class)
    obj.prettysize <- napply(names, function(x) {
                           format(utils::object.size(x), units = "auto") })
    obj.size <- napply(names, object.size)
    obj.dim <- t(napply(names, function(x)
                        as.numeric(dim(x))[1:2]))
    vec <- is.na(obj.dim)[, 1] & (obj.type != "function")
    obj.dim[vec, 1] <- napply(names, length)[vec]
    out <- data.frame(obj.type, obj.size, obj.prettysize, obj.dim)
    names(out) <- c("Type", "Size", "PrettySize", "Length/Rows", "Columns")
    if (!missing(order.by))
        out <- out[order(out[[order.by]], decreasing=decreasing), ]
    if (head)
        out <- head(out, n)
    out
}

# shorthand
lsos <- function(..., n=10) {
    .ls.objects(..., order.by="Size", decreasing=TRUE, head=TRUE, n=n)
}

lsos()

जिसके परिणामस्वरूप निम्न में कुछ है:

                      Type   Size PrettySize Length/Rows Columns
pca.res                 PCA 790128   771.6 Kb          7      NA
DF               data.frame 271040   264.7 Kb        669      50
factor.AgeGender   factanal  12888    12.6 Kb         12      NA
dates            data.frame   9016     8.8 Kb        669       2
sd.                 numeric   3808     3.7 Kb         51      NA
napply             function   2256     2.2 Kb         NA      NA
lsos               function   1944     1.9 Kb         NA      NA
load               loadings   1768     1.7 Kb         12       2
ind.sup             integer    448  448 bytes        102      NA
x                 character     96   96 bytes          1      NA

नोट: मुख्य भाग जो मैंने जोड़ा था (फिर से, जेडी के उत्तर से अनुकूलित):

obj.prettysize <- napply(names, function(x) {
                           print(object.size(x), units = "auto") })

केवल 4 जीबी रैम के साथ (विंडोज 10 चल रहा है, इसलिए इसे लगभग 2 या अधिक यथार्थवादी 1 जीबी बनाएं) मुझे आवंटन के साथ सावधान रहना होगा।

मैं डेटाटेबल का उपयोग लगभग विशेष रूप से करता हूं।

'फ्रेड' फ़ंक्शन आपको आयात पर फ़ील्ड नामों से जानकारी को सब्सक्राइब करने की अनुमति देता है; केवल उन फ़ील्ड को आयात करें जिन्हें वास्तव में शुरू करने के लिए आवश्यक हैं। यदि आप आधार आर पढ़ रहे हैं, तो आयात के तुरंत बाद नकली कॉलम को हटा दें।

जैसा कि 42- सुझाव देता है, जहां भी संभव हो, मैं जानकारी आयात करने के तुरंत बाद कॉलम के भीतर सबसेट कर दूंगा।

जैसे ही उन्हें अब आवश्यकता नहीं होती है, पर्यावरण से अक्सर आरएम () ऑब्जेक्ट्स, उदाहरण के लिए अगली पंक्ति पर उन्हें किसी और चीज को सब्सक्राइब करने के बाद, और gc () को कॉल करें।

डेटा आर से पढ़ने और 'fwrite' बेस आर पढ़ने और लिखने के साथ तुलना करके बहुत तेजी से हो सकता है।

जैसा कि kpierce8 बताता है, मैं लगभग हमेशा पर्यावरण से बाहर सबकुछ लिखता हूं और इसे हजारों / सैकड़ों हजारों फाइलों के माध्यम से प्राप्त करने के लिए भी वापस चला जाता हूं। यह न केवल पर्यावरण को 'साफ' रखता है और स्मृति आवंटन को कम रखता है, लेकिन संभावित रूप से उपलब्ध RAM की गंभीर कमी के कारण, आर के पास अक्सर मेरे कंप्यूटर पर क्रैश होने की प्रवृत्ति होती है; वास्तव में अक्सर। कोड को स्वयं ड्राइव पर बैक अप लेने के बाद कोड विभिन्न चरणों के माध्यम से प्रगति करता है, इसका मतलब है कि अगर यह दुर्घटनाग्रस्त हो जाता है तो मुझे शुरुआत से ही शुरुआत नहीं करना पड़ेगा।

2017 तक, मुझे लगता है कि एम 2 बंदरगाह के माध्यम से सबसे तेज़ एसएसडी प्रति सेकंड कुछ जीबी के आसपास चल रहे हैं। मेरे पास वास्तव में मूल 50 जीबी किंग्स्टन वी 300 (550 एमबी / एस) एसएसडी है जो मैं अपनी प्राथमिक डिस्क के रूप में उपयोग करता हूं (इसमें विंडोज और आर है)। मैं एक सस्ता 500 जीबी डब्ल्यूडी प्लेटर पर सभी थोक जानकारी रखता हूं। जब मैं उन पर काम करना शुरू करता हूं तो मैं डेटा सेट को एसएसडी में ले जाता हूं। यह 'fread'ing' और 'fwrite'ing' के साथ संयुक्त सब कुछ महान काम कर रहा है। मैंने 'एफएफ' का उपयोग करने की कोशिश की है लेकिन पूर्व को पसंद करते हैं। 4K पढ़ने / लिखने की गति हालांकि इसके साथ समस्याएं पैदा कर सकती है; एसएसडी से प्लेटर तक लाखों 1k फ़ाइलों (250 एमबी मूल्य) की एक चौथाई का बैक अप लेने में घंटों लग सकते हैं। जहां तक ​​मुझे पता है, अभी तक कोई आर पैकेज उपलब्ध नहीं है जो स्वचालित रूप से 'चंकिफिकेशन' प्रक्रिया को अनुकूलित कर सकता है; उदाहरण के लिए देखें कि उपयोगकर्ता के पास कितनी रैम है, रैम की पढ़ने / लिखने की गति / सभी ड्राइव कनेक्ट की जांच करें और फिर इष्टतम 'चंकिफिकेशन' प्रोटोकॉल का सुझाव दें। यह कुछ महत्वपूर्ण वर्कफ़्लो सुधार / संसाधन अनुकूलन उत्पन्न कर सकता है; उदाहरण के लिए इसे विभाजित करें ... राम के लिए एमबी -> इसे विभाजित करें ... एसएसडी के लिए एमबी -> इसे विभाजित करें ... प्लेट पर एमबी -> इसे विभाजित करें ... टेप पर एमबी। यह पहले से डेटा सेट को नमूना दे सकता है ताकि इसे काम करने के लिए एक और यथार्थवादी गेज स्टिक दिया जा सके।

आर में जिन समस्याओं पर मैंने काम किया है उनमें बहुत सी समस्याएं संयोजन और क्रमपरिवर्तन जोड़े, ट्रिपल इत्यादि शामिल हैं, जो सीमित सीमा को अधिक सीमित बनाता है क्योंकि वे अक्सर कम से कम किसी बिंदु पर विस्तार से विस्तारित होते हैं। इसने मुझे गुणवत्ता पर बहुत अधिक ध्यान केंद्रित किया है, साथ ही साथ इसे शुरू करने की कोशिश करने के बजाए, और बाद में जानकारी तैयार करने के लिए परिचालन के अनुक्रम पर शुरू होने के साथ शुरू होने वाली जानकारी की मात्रा के विपरीत (शुरुआत के साथ सबसे सरल ऑपरेशन और जटिलता में वृद्धि); उदाहरण के लिए सबसेट, फिर विलय / जुड़ें, फिर संयोजन / क्रमपरिवर्तन आदि बनाएं।

बेस आर पढ़ने और कुछ मामलों में लिखने के लिए कुछ फायदे हैं। उदाहरण के लिए, 'फ्रेड' के भीतर त्रुटि का पता लगाना इतना अच्छा है कि इसे साफ़ करने के लिए आर में वास्तव में गन्दा जानकारी प्राप्त करने में मुश्किल हो सकती है। यदि आप लिनक्स का उपयोग कर रहे हैं तो बेस आर भी बहुत आसान लगता है। बेस आर लिनक्स में ठीक काम करता प्रतीत होता है, विंडोज 10 ~ 20 जीबी डिस्क स्पेस का उपयोग करता है जबकि उबंटू को केवल कुछ जीबी की जरूरत होती है, उबंटू के साथ जरूरी रैम थोड़ा कम है। लेकिन मैंने एलबी पार्टी पैकेज (एल) उबंटू में स्थापित करते समय बड़ी मात्रा में चेतावनियां और त्रुटियों को देखा है। मैं लिनक्स के साथ (एल) उबंटू या अन्य स्टॉक डिस्ट्रीब्यूशन से बहुत दूर बहने की सिफारिश नहीं करता क्योंकि आप प्रक्रिया को लगभग व्यर्थता प्रदान करते हैं, इसलिए मुझे लगता है कि यह एकता है (मुझे लगता है कि 'एकता' को उबंटू में 2017 के रूप में रद्द किया जाना है )। मुझे एहसास है कि यह कुछ लिनक्स उपयोगकर्ताओं के साथ अच्छी तरह से नीचे नहीं जायेगा लेकिन कुछ कस्टम वितरण कुछ नवीनता से परे सीमा रेखा रहित हैं (मैंने अकेले लिनक्स का उपयोग करके वर्षों बिताए हैं)।

उम्मीद है कि उनमें से कुछ दूसरों की मदद कर सकते हैं।


चल रहा है

for (i in 1:10) 
    gc(reset = T)

समय-समय पर आर को अप्रयुक्त मुक्त करने में मदद करता है लेकिन अभी भी स्मृति जारी नहीं किया जाता है।


दुर्भाग्यवश मेरे पास व्यापक रूप से परीक्षण करने का समय नहीं था, लेकिन यहां एक मेमोरी टिप है जिसे मैंने पहले नहीं देखा है। मेरे लिए आवश्यक स्मृति 50% से अधिक के साथ कम कर दिया गया था। जब आप आर में सामान पढ़ते हैं उदाहरण के लिए read.csv उन्हें स्मृति की एक निश्चित मात्रा की आवश्यकता होती है। इसके बाद आप उन्हें सहेजने के साथ save("Destinationfile",list=ls()) अगली बार जब आप आर खोलेंगे तो आप load("Destinationfile") उपयोग कर सकते हैं अब स्मृति उपयोग में कमी आई है। यह अच्छा होगा अगर कोई यह पुष्टि कर सके कि यह एक अलग डेटासेट के साथ समान परिणाम उत्पन्न करता है या नहीं।


मुझे Dirk's .ls.objects () स्क्रिप्ट पसंद है, लेकिन मैंने आकार कॉलम में वर्णों की गणना करने के लिए squinting रखा। तो मैंने आकार के लिए सुंदर स्वरूपण के साथ प्रस्तुत करने के लिए कुछ बदसूरत हैक किया:

.ls.objects <- function (pos = 1, pattern, order.by,
                        decreasing=FALSE, head=FALSE, n=5) {
    napply <- function(names, fn) sapply(names, function(x)
                                         fn(get(x, pos = pos)))
    names <- ls(pos = pos, pattern = pattern)
    obj.class <- napply(names, function(x) as.character(class(x))[1])
    obj.mode <- napply(names, mode)
    obj.type <- ifelse(is.na(obj.class), obj.mode, obj.class)
    obj.size <- napply(names, object.size)
    obj.prettysize <- sapply(obj.size, function(r) prettyNum(r, big.mark = ",") )
    obj.dim <- t(napply(names, function(x)
                        as.numeric(dim(x))[1:2]))
    vec <- is.na(obj.dim)[, 1] & (obj.type != "function")
    obj.dim[vec, 1] <- napply(names, length)[vec]
    out <- data.frame(obj.type, obj.size,obj.prettysize, obj.dim)
    names(out) <- c("Type", "Size", "PrettySize", "Rows", "Columns")
    if (!missing(order.by))
        out <- out[order(out[[order.by]], decreasing=decreasing), ]
        out <- out[c("Type", "PrettySize", "Rows", "Columns")]
        names(out) <- c("Type", "Size", "Rows", "Columns")
    if (head)
        out <- head(out, n)
    out
}

मैं data.table पैकेज का उपयोग करता data.table । इसके साथ := ऑपरेटर आप कर सकते हैं:

  • संदर्भ द्वारा कॉलम जोड़ें
  • संदर्भ के अनुसार मौजूदा कॉलम के सबसेट संशोधित करें, और संदर्भ द्वारा समूह द्वारा संशोधित करें
  • संदर्भ द्वारा कॉलम हटाएं

इनमें से कोई भी ऑपरेशन (संभावित रूप से बड़ा) data.table कॉपी नहीं करता है, यहां तक ​​कि एक बार भी नहीं।

  • एकत्रीकरण भी विशेष रूप से तेज़ है क्योंकि data.table बहुत कम काम करने वाली मेमोरी का उपयोग करता है।

सम्बंधित लिंक्स :


मैं Dirk द्वारा विकसित उन्नत वस्तुओं के काम की तरह काफी पसंद है। हालांकि अधिकांश समय, ऑब्जेक्ट नाम और आकार के साथ एक और बुनियादी आउटपुट मेरे लिए पर्याप्त है। यहां एक समान उद्देश्य के साथ एक सरल कार्य है। मेमोरी उपयोग को वर्णानुक्रम या आकार के अनुसार आदेश दिया जा सकता है, वस्तुओं की एक निश्चित संख्या तक ही सीमित किया जा सकता है, और आरोही या अवरोही का आदेश दिया जा सकता है। साथ ही, मैं अक्सर डेटा के साथ काम करता हूं जो 1 जीबी + है, इसलिए फ़ंक्शन तदनुसार इकाइयों को बदलता है।

showMemoryUse <- function(sort="size", decreasing=FALSE, limit) {

  objectList <- ls(parent.frame())

  oneKB <- 1024
  oneMB <- 1048576
  oneGB <- 1073741824

  memoryUse <- sapply(objectList, function(x) as.numeric(object.size(eval(parse(text=x)))))

  memListing <- sapply(memoryUse, function(size) {
        if (size >= oneGB) return(paste(round(size/oneGB,2), "GB"))
        else if (size >= oneMB) return(paste(round(size/oneMB,2), "MB"))
        else if (size >= oneKB) return(paste(round(size/oneKB,2), "kB"))
        else return(paste(size, "bytes"))
      })

  memListing <- data.frame(objectName=names(memListing),memorySize=memListing,row.names=NULL)

  if (sort=="alphabetical") memListing <- memListing[order(memListing$objectName,decreasing=decreasing),] 
  else memListing <- memListing[order(memoryUse,decreasing=decreasing),] #will run if sort not specified or "size"

  if(!missing(limit)) memListing <- memListing[1:limit,]

  print(memListing, row.names=FALSE)
  return(invisible(memListing))
}

और यहां कुछ उदाहरण आउटपुट है:

> showMemoryUse(decreasing=TRUE, limit=5)
      objectName memorySize
       coherData  713.75 MB
 spec.pgram_mine  149.63 kB
       stoch.reg  145.88 kB
      describeBy    82.5 kB
      lmBandpass   68.41 kB

मैं वास्तव में ऊपर दिए गए कुछ उत्तरों की सराहना करता हूं, @ हैडली और @ डर्क के बाद जो आर को बंद करने और source जारी करने और कमांड लाइन का उपयोग करने का सुझाव देते हैं, मैं ऐसे समाधान के साथ आता हूं जो मेरे लिए बहुत अच्छा काम करता है। मुझे सैकड़ों द्रव्यमान स्पेक्ट्रस से निपटना पड़ा, प्रत्येक में लगभग 20 एमबी मेमोरी है, इसलिए मैंने दो आर स्क्रिप्ट का उपयोग किया, जैसा कि निम्नानुसार है:

पहले एक रैपर:

#!/usr/bin/Rscript --vanilla --default-packages=utils

for(l in 1:length(fdir)) {

   for(k in 1:length(fds)) {
     system(paste("Rscript runConsensus.r", l, k))
   }
}

इस स्क्रिप्ट के साथ मैं मूल रूप से नियंत्रित करता हूं कि मेरी मुख्य स्क्रिप्ट क्या runConsensus.r है। runConsensus.r , और मैं आउटपुट के लिए डेटा उत्तर लिखता हूं। इसके साथ, प्रत्येक बार जब रैपर स्क्रिप्ट को कॉल करता है तो ऐसा लगता है कि आर फिर से खोला गया है और स्मृति मुक्त हो गई है।

आशा करता हूँ की ये काम करेगा।


यदि आप लिनक्स पर काम कर रहे हैं और कई प्रक्रियाओं का उपयोग करना चाहते हैं और केवल एक या अधिक बड़ी वस्तुओं पर पढ़ने के संचालन करना है तो makeForkCluster बजाय makeForkCluster उपयोग करें। यह आपको अन्य प्रक्रियाओं को बड़ी वस्तु भेजने का समय भी बचाता है।


यदि आप वास्तव में लीक से बचना चाहते हैं, तो आपको वैश्विक पर्यावरण में किसी भी बड़ी वस्तुएं बनाने से बचना चाहिए।

जो मैं आमतौर पर करता हूं वह एक ऐसा कार्य होता है जो नौकरी करता है और NULL लौटाता NULL - इस डेटा या अन्य लोगों द्वारा कॉल किए जाने वाले सभी डेटा को पढ़ और छेड़छाड़ की जाती है।


यह उपर्युक्त को कुछ भी नहीं जोड़ता है, लेकिन मुझे पसंद की सरल और भारी टिप्पणी वाली शैली में लिखा गया है। यह आकार में आदेशित वस्तुओं के साथ एक टेबल उत्पन्न करता है, लेकिन ऊपर दिए गए उदाहरणों में दिए गए कुछ विवरणों के बिना:

#Find the objects       
MemoryObjects = ls()    
#Create an array
MemoryAssessmentTable=array(NA,dim=c(length(MemoryObjects),2))
#Name the columns
colnames(MemoryAssessmentTable)=c("object","bytes")
#Define the first column as the objects
MemoryAssessmentTable[,1]=MemoryObjects
#Define a function to determine size        
MemoryAssessmentFunction=function(x){object.size(get(x))}
#Apply the function to the objects
MemoryAssessmentTable[,2]=t(t(sapply(MemoryAssessmentTable[,1],MemoryAssessmentFunction)))
#Produce a table with the largest objects first
noquote(MemoryAssessmentTable[rev(order(as.numeric(MemoryAssessmentTable[,2]))),])

यह एक अच्छी चाल है।

एक अन्य सुझाव स्मृति कुशल वस्तुओं का उपयोग जहां भी संभव हो: उदाहरण के लिए, डेटा.फ्रेम के बजाय मैट्रिक्स का उपयोग करें।

यह वास्तव में स्मृति प्रबंधन को संबोधित नहीं करता है, लेकिन एक महत्वपूर्ण कार्य जिसे व्यापक रूप से ज्ञात नहीं है स्मृति है .limit ()। आप इस कमांड का उपयोग कर डिफ़ॉल्ट बढ़ा सकते हैं, memory.limit (आकार = 2500), जहां आकार एमबी में है। जैसा कि डिर्क ने उल्लेख किया है, आपको इसका वास्तविक लाभ लेने के लिए 64-बिट का उपयोग करने की आवश्यकता है।


वस्तुओं की संग्रह को संभालने के लिए सूचियों के बजाय वातावरण का उपयोग जो कामकाजी स्मृति की एक बड़ी मात्रा में है।

कारण: प्रत्येक बार एक list संरचना का एक तत्व संशोधित किया जाता है, पूरी सूची अस्थायी रूप से डुप्लिकेट की जाती है। यह एक मुद्दा बन जाता है यदि सूची की संग्रहण आवश्यकता लगभग उपलब्ध वर्किंग मेमोरी है, क्योंकि तब डेटा धीमी हार्ड डिस्क पर बदलना पड़ता है। दूसरी ओर, पर्यावरण इस व्यवहार के अधीन नहीं हैं और इन्हें सूचियों के समान माना जा सकता है।

यहाँ एक उदाहरण है:

get.data <- function(x)
{
  # get some data based on x
  return(paste("data from",x))
}

collect.data <- function(i,x,env)
{
  # get some data
  data <- get.data(x[[i]])
  # store data into environment
  element.name <- paste("V",i,sep="")
  env[[element.name]] <- data
  return(NULL)  
}

better.list <- new.env()
filenames <- c("file1","file2","file3")
lapply(seq_along(filenames),collect.data,x=filenames,env=better.list)

# read/write access
print(better.list[["V1"]])
better.list[["V2"]] <- "testdata"
# number of list elements
length(ls(better.list))

big.matrix या data.table जैसे संरचनाओं के संयोजन के साथ जो उनकी सामग्री को स्थानांतरित करने की अनुमति देता है, बहुत ही कुशल स्मृति उपयोग प्राप्त किया जा सकता है।


साथ ही ऊपर दिए गए उत्तरों में दी गई अधिक सामान्य मेमोरी प्रबंधन तकनीकों के साथ, मैं हमेशा तक अपनी ऑब्जेक्ट्स के आकार को जितना संभव हो कम करने की कोशिश करता हूं। उदाहरण के लिए, मैं बहुत बड़े लेकिन बहुत स्पैर मैट्रिस के साथ काम करता हूं, दूसरे शब्दों में मैट्रिस जहां अधिकांश मान शून्य होते हैं। 'मैट्रिक्स' पैकेज (पूंजीकरण महत्वपूर्ण) का उपयोग करके मैं अपने औसत ऑब्जेक्ट आकार को ~ 2GB से ~ 200MB तक कम करने में सक्षम था:

my.matrix <- Matrix(my.matrix)

मैट्रिक्स पैकेज में डेटा प्रारूप शामिल हैं जिनका उपयोग नियमित मैट्रिक्स (आपके अन्य कोड को बदलने की कोई आवश्यकता नहीं है) के रूप में किया जा सकता है, लेकिन स्पैस डेटा को अधिक कुशलता से स्टोर करने में सक्षम हैं, चाहे स्मृति में लोड हो या डिस्क में सहेजा गया हो।

इसके अतिरिक्त, मुझे प्राप्त होने वाली कच्ची फ़ाइलें 'लंबे' प्रारूप में हैं जहां प्रत्येक डेटा पॉइंट में चर x, y, z, i । डेटा को x * y * z आयाम सरणी में केवल परिवर्तनीय i साथ बदलने के लिए अधिक कुशल।

अपने डेटा को जानें और थोड़ी सी सामान्य समझ का उपयोग करें।


gData पैकेज में काम करेगा प्रत्येक ऑब्जेक्ट का मेमोरी उपयोग भी दिखा सकता है।

gdata::ll(unit='MB')






r