R筆記 R的記憶體管理和垃圾清理

2022-07-17 10:00:14 字數 3026 閱讀 4063

筆記:

1、r輸入命令時速度不要太快,終究是個統計軟體,不是程式設計!

2、memory.limit()檢視當前作業系統分配記憶體給r的最大限度(單位是m?)

3、要經常 rm(object) 或者 rm(list=ls()) 和 gc()釋放記憶體空間

4、盡量提前設定矩陣大小固定不變,矩陣每增長一次,即使賦給同名的變數,都需要新開闢一塊更大的空間

5、盡量避免迴圈語句

6、用矩陣,而不是資料框

7、在大資料集執行前現在子資料集上測試程式

8、將資料儲存到r的住記憶體之外的包:

biglm和speedglm包能以高效的形式實現大型資料的線性模型擬合和廣義線性模型擬合

分析bigmemory包生成的矩陣:

biglar包跟ff配合使用,為在記憶體中無法放至的大資料提供了最小角回歸,lasso和逐步回歸分析。

borbdingnag包可以處理大數字(大於2的1024次方的數)

寫r程式的人,相信都會遇到過「cannot allocate vector of size」或者「無法分配大小為...的向量」這樣的錯誤。原因很簡單,基本都是產生乙個大矩陣等物件時發生的,最乾脆的解決辦法有兩種,第一種是加大記憶體換64位系統,第二種是改變演算法避免如此大的物件。第一種辦法,是最好的辦法,不過大物件的需求是沒有止盡的,終究不是長久之道。第二種辦法是最好的思路,無論多麼大的物件都是可以弄小的,無非就是分而治之、時間換空間等,對演算法的研究也是沒有止盡的。

公升級硬體和改進演算法是解決記憶體問題的永恆的辦法,超出了本文想要表述的範圍。在這裡,只是簡單談談r語言的記憶體管理和垃圾清理機制,只有對這些有所了解,才能對任何問題都能找到針對性的解決辦法。

相信所有人在遇到無法分配向量這一問題後,都能很快地找到

改變「--max-mem-size」(假設都是在windows下)或者「memory.limit

」的方法,的確,這是最直接的方法。因為出現新物件無法分配記憶體的直接原因就是記憶體不夠,r獲取記憶體的方式和其他應用程式一樣,都是向作業系統要記憶體,如果無法獲取連續的某個大小的記憶體空間,就會出現無法分配記憶體的錯誤。由於大家使用r時通常都是自動安裝自動執行,作業系統願意分配給r多少記憶體都是採用的預設設定,在r中使用命令memory.size(na)或者memory.limit()可以看到當前設定下作業系統能分配給r的最大記憶體是多少。同時可以

使用memory.size(f)檢視當前r已使用的記憶體,memory.size(t)檢視已分配的記憶體

(注意剛開始時已使用記憶體和已分配記憶體是同步增加的,但是隨著r中的垃圾被清理,已使用記憶體會減少,而已分配給r的記憶體一般不會改變。)。如果memory.limit()得到的數是乙個很小的記憶體,說明作業系統太小氣了,留那麼多記憶體給別的程式用不給r。解決辦法很簡單,就是開啟r時不通過雙擊圖示,而是在「執行」中輸入「rgui --max-mem-size 2gb」(假設要分配2g記憶體且在環境變數中正確設定了r的安裝資料夾),在執行memory.limit()就會發現記憶體加大了,其實更簡單的方法是直接在r中執行memory.limit(2000),效果一模一樣,而且不用重啟r。

可惜大多數情況下改變這個值也不會有效果,因為這個值已經足夠大,那麼無法分配記憶體的原因不是作業系統小氣對r不公,而是它確實拿不出來,誰找它要也拿不出來。這個時候就需要了解r的記憶體管理到底是怎麼回事了。

r的操作基本都是通過變數來實現的,變數可以是各種各樣的物件型別,r中的物件(比如矩陣)在記憶體中存於兩種不同的地方,一種是堆記憶體(heap),其基本單元是「vcells」,每個大小為8位元組,新來乙個物件就會申請一塊空間,把值全部存在這裡,和c裡面的堆記憶體很像。第二種是位址對(cons cells),和lisp裡的cons cells道理一樣,主要用來儲存位址資訊,最小單元一般在32位系統中是28位元組、64位系統中是56位元組。在r中,可以通過ls()來檢視當前所有物件名,對於每乙個物件,可以通過object.size(x)來檢視其占用記憶體的大小。

如果是因為當前物件占用記憶體過多,那麼可以通過處理物件來獲取更大的可用記憶體。乙個很有用的方法是改變物件的儲存模式,通過

storage.mode(x)可以看到某個物件的儲存模式

,比如某個矩陣預設就是「double」的,如果這個矩陣的數值都是整數甚至0-1,完全沒必要使用double來占用空間,可以使用storage.mode(x) <- "integer"將其改為整數型,可以看到該物件的大小會變為原來的一半。

對於當前物件占用記憶體過多的情況,乙個很主要的原因就是在寫程式的過程中造成了太多的中間物件,r是乙個很方便的語言,大家使用它一般都是寫各種複雜的模型和演算法,很多問題構造幾個矩陣經過一系列的矩陣運算就可以很快解決,但是這些輔助演算法的大矩陣如果不清理,就會留在系統中佔記憶體。因此在寫程式中對於中間物件,經常使用

rm(x)是乙個很好的習慣,如果是非常重要的資訊不想刪掉,可以存在硬碟裡,比如csv檔案或者rsqlite等

。垃圾處理函式gc(),將會立刻釋放空間

。但是通常不是很必要,因為當記憶體不夠時系統會自動清理垃圾的,我們要做的只是將不再使用的物件rm()掉,在寫r程式時應該養成習慣。

很多時候,在程式中尤其是迴圈裡,如果記憶體處理不當,還沒來得及垃圾清理,就會把記憶體撐爆,因此新建物件時一定要考慮到r的記憶體管理機制。大家都知道r中矩陣的維度並不需要賦乙個固定的值(很多語言的陣列長度不能為變數),這為寫程式帶來了極大的方便,因此經常在迴圈中會出現某個矩陣越來越長的情況,實際上,

矩陣每增長一次,即使賦給同名的變數,都需要新開闢一塊更大的空間

,假設初始矩陣為100k,第二個為101k,一直增到120k,那麼,將會分別開闢100k、101k一直到120k的連續堆記憶體,如果

一開始就開一塊120k的,使之從101k逐漸增長到120k,將會大大地節約記憶體

。cbind函式也是這個道理,所以在迴圈中要注意不要濫用。

要處理好記憶體的問題其實很簡單,養成隨時關注記憶體的習慣即可,每新建乙個物件或者迴圈賦值的時候適當估算一下所佔記憶體,大記憶體的中間變數用完後記得清理。如果實在需要新建乙個巨大的物件,那麼就該考慮一些

專門處理大記憶體物件以及並行處理的包,比如bigmemory

等有人問過類似的問題:

除了 hadoop 以外,似乎 colbycol 包是方案之一:

另,stackoverflow 第七章的範例:

來自為知筆記(wiz)

R語言記憶體管理

r中的物件 比如矩陣 在記憶體中存於兩種不同的地方 第一種是堆記憶體 heap 其基本單元是 vcells 每個大小為8位元組,新來乙個物件就會申請一塊空間,把值全部存在這裡,和c裡面的堆記憶體很像 第二種是位址對 cons cells 主要用來儲存位址資訊,最小單元一般在32位系統中是28位元組 ...

2021美賽準備 記憶體管理(R語言)

總結win 10中的r語言常見的記憶體管理命令在基礎包和pryr包裡,我一般處理大點的資料單純用基礎包裡的函式,所以本文介紹的命令來自基礎包的函式。因為r裡的記憶體上限和電腦的配置是有關係的,所以先給大家看一下相關的引數。我的電腦是8g的運存。大家在此電腦 右鍵 屬性可以檢視自己電腦的記憶體。我用的...

我的R學習筆記

1 the workspace.來自 r in acation 要點注釋 chapter 1 mac setwd desktop r windows setwd c myprojects project1 我的win10 setwd c users administrator desktop r 意...