2013-05-30 21 views
1

在我當前的項目中,我有一個計算函數,它在向量A的一個元素上運行,並返回一個列表元素,我將其插入到列表B中。返回元素包含許多與第一個列表相關的任意大小的矩陣。如何以內存有效的方式將結果保存在列表中?

作爲一個例子,我們來看一個函數,它取一個原始數n並生成一個n×n的隨機矩陣。

vector.A <- sample(1:2000, 15000, replace = TRUE) 

list.B <- as.list(rep(NA, length(vector.A))) 

arbitraryMatrix <- function(n) { 
    matrix(rnorm(n*n), ncol = n, nrow = n) 
} 

for (i in which(is.na(list.B))) { 
    print(i) 
    list.B[[i]] <- arbitraryMatrix(vector.A[i]) 
} 

此功能會減慢較大list.B得到(其實我敢肯定它完成循環之前就會死機R)。我想到了list.B中沒有元素在創建後再次被訪問,所以它可以寫入磁盤而不是以減慢計算速度的方式佔用內存。

我可以編寫一個腳本,通過將塊保存到.rda文件中來實現此目的,但我希望有人有更優雅的解決方案。

FF包看起來像這個 http://cran.r-project.org/web/packages/ff/ff.pdf 有趣的可能性,但據我所知它不支持列表對象。

注意事項:

  • 我使用了一個for循環,因爲我希望能夠修復的第七千迭代中出現的錯誤,而無需重新運行不必要的第6999次迭代。
  • 根據您的機器編輯代碼的參數,直到它可以運行,但只能在您的計算機上緩慢運行。
  • 我有一個列表作爲其輸入的實際問題,所以我對向量化任意矩陣函數不感興趣。
  • 內存問題在我的實際問題中複雜化,因爲函數使用大量內存(它涉及數據框的子集)。

編輯:我正在考慮將r對象映射到臨時文件的mmap包,但我仍試圖解決如何使用它解決此問題。

+0

請不要在標題中放置標籤_redundant_。 –

+0

如果再次訪問列表中的任何元素,是否有任何需要將其放入列表中? – James

+0

稍後它將被不同的R程序訪問,但是對於該過程的這一步它只需要被計算和存儲。 –

回答

2

下面是使用軟件包的答案。這是一個很好的方法,因爲它具有令人印象深刻的微小內存佔用量,隨着功能的進步,這個數量幾乎不會增加。所以這是你的目標之一。

然而,這是一個糟糕的方法,因爲它有兩個顯着的缺點(1)它是慢得令人難以置信,如果你打開一個進程監視器可以看到磁盤和內存交換在一個相當悠閒率回事(至少在我的機器上)。事實上,它很慢,我不確定它是否會隨着它的進一步變慢而變慢。我還沒有完成它,只是在我在內存中運行函數(關於項目350左右)時出現錯誤以說服自己比在內存中運行更好(此時磁盤對象是73 GB)。這是第二個缺點,創建的磁盤對象是海量的

所以,這裏希望別人能更好地回答您的問題(可能與mmap?),我會非常感興趣的看到。

# set up disk storage object 
library(filehash) 
dbCreate("myTestDB") 
db <- dbInit("myTestDB") 

# put data on disk 
db$A <- sample(1:2000, 15000, replace = TRUE) 
db$B <- as.list(rep(NA, length(db$A))) 

# function 
arbitraryMatrix <- function(n) { 
    matrix(rnorm(n*n), ncol = n, nrow = n) 
} 

# run function by accessing disk objects 
for (i in which(is.na(db$B))) { 
    print(i) 
    db$B[[i]] <- arbitraryMatrix(db$A[i]) 
} 

# run function by accessing disk objects, following 
# Jon's comment to treat db as a list 
for (i in which(is.na(db$B))) { 
    print(i) 
    db[[as.character(i)]] <- arbitraryMatrix(db$A[i]) 
} 
# use db[[as.character(1)]] etc to access the list items 
+0

雖然它給我的例子可能有點慢,但對於我在工作中遇到的問題(該功能大約需要4秒鐘才能在最佳條件下運行),它確實非常出色。但我同意看到使用其他一些功能的例子會很高興。 –

+0

此外,如果您將db視爲列表,即將每個元素放入db [[as.character(i)]],讀/寫工作會更快。目前我認爲你的腳本可能不得不在磁盤上的列表中搜索,這可能會減慢速度,但我可能是錯的。 –

+0

是的,這是一個有趣的想法,我已經添加到我的答案。我的快速基準測試表明速度並不快(60個vs 150個項目的62個),但可能會增加一個更長的列表。 – Ben

相關問題