2013-05-30 2 views
1

현재 프로젝트에서는 벡터 A의 한 요소에서 실행되는 계산 함수를 사용하여 목록 B에 삽입하는 목록 요소를 반환합니다. 반환 요소에는 첫 번째 목록과 관련된 여러 개의 임의 크기의 큰 행렬이 포함되어 있습니다.결과를 메모리 효율적인 방식으로 목록에 저장할 수 있습니까?

예를 들어 원래 번호 n을 사용하고 n x 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 그러나 목록 개체를 지원하지 않는다고 말할 수 있습니다.

주의 사항 : I 불필요 처음 6999 반복을 다시 실행하지 않고도 7천번째 반복에 발생하는 버그를 복구 할 수 있기를 좋아하기 때문에 내가 루프를 사용하고

  • .
  • 컴퓨터에 따라 코드가 실행될 때까지 매개 변수를 편집하지만
    컴퓨터에서만 천천히 조정하십시오.
  • 실제의 문제는 목록을 입력으로 사용하므로 arbitraryMatrix 함수를 벡터화하는 데 관심이 없습니다.
  • 함수는 많은 메모리를 사용하기 때문에 실제 문제는 메모리 문제가됩니다 (데이터 프레임의 서브 세트가 포함됨).

편집 : 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

예, 흥미로운 아이디어를 그만두고, 제 답변에 추가했습니다. 나의 빠른 벤치마킹은 훨씬 빠르지 않다는 것을 보여 주지만 (150 개 항목에 대해 60 초 대 62 초) 긴 목록이 추가 될 수 있습니다. – Ben