Programing

R 세션에서 사용 가능한 메모리를 관리하기위한 요령

lottogame 2020. 2. 14. 21:55
반응형

R 세션에서 사용 가능한 메모리를 관리하기위한 요령


사람들이 대화 형 R 세션의 사용 가능한 메모리를 관리하기 위해 어떤 트릭을 사용합니까? 아래 기능 ([Petr Pikal 및 David Hinds가 2004 년 r-help 목록에 게시 한 내용을 기반으로])을 사용하여 가장 큰 객체를 나열하고 rm()일부 를 간헐적 으로 나열합니다. 그러나 지금까지 가장 효과적인 솔루션은 메모리가 충분한 64 비트 Linux에서 실행하는 것입니다.

다른 좋은 트릭 사람들이 공유하고 싶어? 게시물 당 하나주세요.

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

재생 가능한 스크립트로 작업을 기록하십시오. 때때로 R을 다시 연 다음 source()스크립트를 다시여 십시오. 더 이상 사용하지 않는 것을 정리하면 추가 혜택으로 코드를 테스트하게됩니다.


data.table 패키지를 사용합니다 . :=연산자를 사용하면 다음을 수행 할 수 있습니다.

  • 참조로 열 추가
  • 참조 및 그룹별로 기존 열의 하위 집합 수정
  • 참조로 열 삭제

이러한 작업 중 어느 것도 (잠재적으로 큰) 전혀 복사 data.table하지 않습니다.

  • data.table작업 메모리가 훨씬 적게 사용 되므로 집계가 특히 빠릅니다 .

관련된 링크들 :


트위터 포스트에서 이것을 보았고 Dirk의 멋진 기능이라고 생각하십시오! JD Long의 답변에 따라 사용자 친화적 인 독서를 위해이 작업을 수행합니다.

# 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

참고 : 내가 추가 한 주요 부분은 (JD의 답변에서 다시 한 번)입니다.

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

Dirk의 .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
}

회귀 함수 subsetdata=인수에 데이터 프레임을 전달할 때 필요한 변수 만 선택 하여 매개 변수를 적극적으로 사용 합니다. 수식과 select=벡터 에 변수를 추가하는 것을 잊어 버린 경우 약간의 오류가 발생 하지만 객체 복사가 줄어들어 메모리 시간이 크게 줄어 여전히 많은 시간을 절약합니다. 110 개의 변수를 가진 4 백만 개의 레코드가 있다고 가정 해 봅시다. 예 :

# library(rms); library(Hmisc) for the cph,and rcs functions
Mayo.PrCr.rbc.mdl <- 
cph(formula = Surv(surv.yr, death) ~ age + Sex + nsmkr + rcs(Mayo, 4) + 
                                     rcs(PrCr.rat, 3) +  rbc.cat * Sex, 
     data = subset(set1HLI,  gdlab2 & HIVfinal == "Negative", 
                           select = c("surv.yr", "death", "PrCr.rat", "Mayo", 
                                      "age", "Sex", "nsmkr", "rbc.cat")
   )            )

맥락과 전략을 설정하는 방법 : gdlab2변수는 여러 실험실 테스트에 대해 모든 정상 또는 거의 정상 값을 가진 데이터 세트의 피험자에 대해 구성된 논리 벡터 HIVfinal이며 HIV에 대한 예비 및 확인 테스트를 요약 한 문자 벡터입니다. .


좋은 속임수입니다.

다른 제안은 가능한 한 메모리 효율적인 객체를 사용하는 것입니다. 예를 들어 data.frame 대신 행렬을 사용하십시오.

이것은 실제로 메모리 관리를 다루지는 않지만 널리 알려지지 않은 중요한 함수 중 하나는 memory.limit ()입니다. 이 명령 memory.limit (size = 2500)를 사용하여 기본값을 늘릴 수 있습니다. 여기서 크기는 MB입니다. Dirk가 언급했듯이, 이것을 활용하려면 64 비트를 사용해야합니다.


Dirk가 개발 한 개선 된 객체 기능을 매우 좋아합니다. 그러나 대부분의 경우 객체 이름과 크기가 더 기본적인 출력으로 충분합니다. 비슷한 목표를 가진 간단한 함수가 있습니다. 메모리 사용은 알파벳순 또는 크기 순으로 정렬 될 수 있으며, 특정 개수의 객체로 제한 될 수 있으며 오름차순 또는 내림차순으로 정렬 될 수 있습니다. 또한 종종 1GB 이상의 데이터로 작업하므로 함수가 단위를 변경합니다.

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

R 작업 공간을 저장하지 않습니다. 가져 오기 스크립트와 데이터 스크립트를 사용하고 자주 파일로 다시 만들고 싶지 않은 특히 큰 데이터 개체를 출력합니다. 이 방법으로 나는 항상 신선한 작업 공간으로 시작하며 큰 물체를 정리할 필요가 없습니다. 그래도 아주 좋은 기능입니다.


불행히도 나는 그것을 광범위하게 테스트 할 시간이 없었지만 여기에 내가 보지 못한 메모리 팁이 있습니다. 나에게 필요한 메모리는 50 % 이상 줄었다. read.csv와 같이 R로 내용을 읽을 때는 특정 양의 메모리가 필요합니다. save("Destinationfile",list=ls())다음에 R을 열면 저장할 수 있습니다 . 다음에 R을 열 때 사용할 수 있습니다. load("Destinationfile")이제 메모리 사용량이 줄어들 수 있습니다. 이것이 다른 데이터 세트로 유사한 결과를 생성하는지 여부를 확인할 수 있다면 좋을 것입니다.


자주 다시 시작하는 일반적인 전략을 자세히 설명 하기 위해 명령 줄에서 간단한 표현식을 직접 실행할 수있는 little사용할 수 있습니다 . 다음은 간단한 크로스 프로드를 위해 때때로 다른 BLAS를 시간 측정하는 데 사용하는 예입니다.

 r -e'N<-3*10^3; M<-matrix(rnorm(N*N),ncol=N); print(system.time(crossprod(M)))'

마찬가지로,

 r -lMatrix -e'example(spMatrix)'

--packages | -l 스위치를 통해 Matrix 패키지를로드하고 spMatrix 함수의 예제를 실행합니다. r은 항상 'fresh'를 시작하므로이 방법은 패키지 개발 중에도 좋은 테스트입니다.

마지막으로 r은 '#! / usr / bin / r'shebang-header를 사용하는 스크립트의 자동 배치 모드에서도 훌륭하게 작동합니다. Rscript는 더 작게 사용할 수없는 대안입니다 (예 : Windows).


속도와 메모리의 목적을 위해 복잡한 일련의 단계를 통해 큰 데이터 프레임을 구축 할 때 주기적으로 디스크에 플러시 (진행중인 데이터 세트를 플러시)하여 이전에 있던 것을 추가 한 다음 다시 시작합니다 . 이런 식으로 중간 단계는 작은 데이터 프레임에서만 작동합니다 (예를 들어 rbind 가 큰 객체 에서는 상당히 느려짐). 모든 중간 오브젝트가 제거되면 프로세스 종료시 전체 데이터 세트를 다시 읽을 수 있습니다.

dfinal <- NULL
first <- TRUE
tempfile <- "dfinal_temp.csv"
for( i in bigloop ) {
    if( !i %% 10000 ) { 
        print( i, "; flushing to disk..." )
        write.table( dfinal, file=tempfile, append=!first, col.names=first )
        first <- FALSE
        dfinal <- NULL   # nuke it
    }

    # ... complex operations here that add data to 'dfinal' data frame  
}
print( "Loop done; flushing to disk and re-reading entire data set..." )
write.table( dfinal, file=tempfile, append=TRUE, col.names=FALSE )
dfinal <- read.table( tempfile )

단지 행렬, 배열, 목록이 아닌 data.frames / tables에 대해서만 data.table패키지가 tables()Dirk의 .ls.objects()사용자 정의 함수 (이전 답변에 자세히 설명되어 있음)를 대체하는 훌륭한 것으로 보입니다 .


  1. 운이 좋으며 큰 데이터 세트는 계측기에 의해 약 100MB (32 비트 이진)의 "청크"(하위 세트)로 저장됩니다. 따라서 데이터 세트를 융합하기 전에 사전 처리 단계 (정보가없는 부분 삭제, 다운 샘플링)를 순차적으로 수행 할 수 있습니다.

  2. gc ()데이터 크기가 사용 가능한 메모리에 가까워지면 "손으로"를 호출 하면 도움이됩니다.

  3. 때로는 다른 알고리즘에 훨씬 적은 메모리가 필요합니다.
    때로는 벡터화와 메모리 사용간에 상충 관계가 있습니다.
    비교 : split& lapplyfor루프.

  4. 빠르고 쉬운 데이터 분석을 위해 데이터의 작은 임의의 하위 집합 ( sample ())을 먼저 사용합니다. 데이터 분석 스크립트 /.Rnw가 완료되면 데이터 분석 코드가 완성되고 완전한 데이터가 야간 / 주말 / ... 계산을 위해 계산 서버로 이동합니다.


많은 양의 작업 메모리를 차지하는 오브젝트 콜렉션을 처리하기 위해 목록 대신 환경 사용.

이유 : 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매우 효율적인 메모리 사용이 달성 될 수 있습니다.


패키지 ll기능 gData은 각 객체의 메모리 사용량을 보여줄 수 있습니다.

gdata::ll(unit='MB')

실제로 누출을 피하려면 글로벌 환경에서 큰 객체를 생성하지 않아야합니다.

내가 일반적으로하는 일은 작업을 수행하고 반환하는 함수를 갖는 것입니다 NULL.이 함수 나 다른 함수에서 모든 데이터를 읽고 조작합니다.


4GB의 RAM (Windows 10을 실행하므로 약 2GB 이상을 현실적으로 1GB로 설정)을 사용하면 할당에 실제로주의해야했습니다.

나는 거의 독점적으로 data.table을 사용합니다.

'fread'기능을 사용하면 가져올 때 필드 이름별로 정보를 서브 세트 할 수 있습니다. 실제로 시작하는 데 필요한 필드 만 가져옵니다. 기본 R 읽기를 사용하는 경우 가져 오기 직후 스퓨리어스 열을 null로 처리하십시오.

으로 42 인치가 제안, 나는 즉시 정보를 가져온 후 열 내에서 부분 집합 곳에 이제까지 가능합니다.

더 이상 필요하지 않은 즉시 환경에서 객체를 자주 rm ()합니다 (예 : 객체를 사용하여 다른 것을 서브 셋팅 한 후 다음 줄). gc ()를 호출합니다.

data.table의 'fread'및 'fwrite'는 기본 R 읽기 및 쓰기와 비교하여 매우 빠릅니다.

kpierce8이 제안 했듯이 , 나는 거의 항상 환경에서 모든 것을 쓸어 버리고 수천 / 수십만 개의 작은 파일을 통해 다시 확산시킵니다 . 이것은 환경을 '깨끗한'상태로 유지하고 메모리 할당을 낮게 유지하지만, 가용 한 RAM 부족으로 인해 R은 내 컴퓨터에서 자주 충돌하는 경향이 있습니다. 정말 자주. 코드가 다양한 단계를 거치면서 드라이브 자체에 정보를 백업한다는 것은 충돌이 발생하더라도 처음부터 시작할 필요가 없음을 의미합니다.

2017 년 현재, 가장 빠른 SSD가 M2 포트를 통해 초당 약 몇 GB를 실행하고 있다고 생각합니다. 기본 디스크로 사용하는 기본 50GB Kingston V300 (550MB / s) SSD가 있습니다 (Windows 및 R이 있음). 나는 모든 대량 정보를 저렴한 500GB WD 플래터에 보관합니다. 작업을 시작할 때 데이터 세트를 SSD로 옮깁니다. 이것은 '확산'및 'fwrite'와 결합하여 모든 것이 훌륭하게 해결되었습니다. 나는 'ff'를 사용해 보았지만 전자를 선호합니다. 4K 읽기 / 쓰기 속도는 이로 인해 문제를 일으킬 수 있습니다. SSD에서 플래터에 백만 개의 1k 파일 (250MB)을 백업하는 데 몇 시간이 걸릴 수 있습니다. 내가 아는 한, '청크 화'프로세스를 자동으로 최적화 할 수있는 R 패키지는 아직 없습니다. 예를 들어 사용자의 RAM 용량을 확인하십시오. 연결된 RAM / 모든 드라이브의 읽기 / 쓰기 속도를 테스트 한 다음 최적의 '청크'프로토콜을 제안하십시오. 이는 상당한 워크 플로우 개선 / 자원 최적화를 생성 할 수 있습니다. 예를 들어 램의 경우 ... MB로 분할-> SSD의 경우 ... MB로 분할-> 플래터에서 ... MB로 분할-> 테이프의 ... MB로 분할합니다. 데이터 세트를 미리 샘플링하여보다 현실적인 게이지 스틱을 사용할 수 있습니다.

내가 R에 근무 한 문제의 많은 그들은 종종하므로 단지 더 제한 제한된 RAM을 가진하게 트리플 등 조합과 순열 쌍 형성 포함 적어도 기하 급수적으로 어떤 점에서 확장을. 이 날이에 많은 관심을 집중했다 품질 반대로 의 정보가 오히려 나중에 그것을 청소하는 것보다, 우선 그들로가는 및 정보를 준비하는 작업의 순서에 (로 시작하는 시작하기 가장 간단한 조작과 복잡성 증가); 예를 들어 부분 집합, 병합 / 결합, 조합 / 순열 등을 형성합니다.

경우에 따라 기본 R 읽기 및 쓰기를 사용하면 이점이있는 것 같습니다. 예를 들어, 'fread'내의 오류 감지가 너무 좋으므로 R로 정보를 정리하기 위해 실제로 지저분한 정보를 얻는 것이 어려울 수 있습니다. Linux를 사용하는 경우 Base R도 훨씬 쉬워 보입니다. 기본 R은 Linux에서 잘 작동하는 것으로 보이며 Windows 10은 ~ 20GB의 디스크 공간을 사용하지만 Ubuntu는 몇 GB 만 ​​필요하며 Ubuntu에 필요한 RAM은 약간 낮습니다. 그러나 (L) 우분투에 타사 패키지를 설치할 때 많은 경고와 오류가 나타났습니다. (L) Ubuntu 또는 Linux와의 다른 주식 배포에서 너무 멀리 떨어져 표류하지 않는 것이 좋습니다. 전체 호환성이 너무 느려서 프로세스가 거의 무의미합니다 (2017 년 현재 Ubuntu에서 'unity'가 취소 될 것으로 생각합니다) ).

잘하면 그 중 일부는 다른 사람들을 도울 수 있습니다.


이것은 위의 내용에 아무것도 추가하지 않지만 내가 좋아하는 간단하고 심하게 주석이 달린 스타일로 작성되었습니다. 크기 순서대로 객체가 있지만 위 예제에 제공된 세부 정보가없는 테이블을 생성합니다.

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

이것은이 훌륭한 오래된 질문에 대한 새로운 답변입니다. 해들리의 고급 R에서 :

install.packages("pryr")

library(pryr)

object_size(1:10)
## 88 B

object_size(mean)
## 832 B

object_size(mtcars)
## 6.74 kB

( http://adv-r.had.co.nz/memory.html )


당신이에서 작업하는 경우 리눅스 와 사용하고자하는 여러 프로세스를 만해야 읽기 하나 이상에 대한 작업을 큰 개체 사용 makeForkCluster대신의 makePSOCKcluster. 또한 큰 개체를 다른 프로세스로 보내는 시간도 절약됩니다.


R을 닫고 source명령 줄을 실행 하고 사용 하는 것을 제안하는 @hadley와 @Dirk에 따라 위의 답변 중 일부에 감사드립니다. 저는 잘 작동하는 솔루션을 생각해 냈습니다. 수백 가지 질량 스펙트럼을 처리해야했으며 각각 약 20MB의 메모리를 차지하므로 다음과 같이 두 개의 R 스크립트를 사용했습니다.

먼저 래퍼 :

#!/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하고 출력에 대한 데이터 응답을 작성합니다. 이를 통해 랩퍼가 스크립트를 호출 할 때마다 R이 다시 열리고 메모리가 해제 된 것 같습니다.

도움이 되길 바랍니다.


위의 답변에 제공된 일반적인 메모리 관리 기술뿐만 아니라 항상 가능한 한 객체 크기를 줄이려고합니다. 예를 들어, 매우 크지 만 매우 희소 행렬, 즉 대부분의 값이 0 인 행렬로 작업합니다. '매트릭스'패키지 (자본화 중요)를 사용하여 다음과 같이 평균 객체 크기를 ~ 2GB에서 ~ 200MB로 줄일 수있었습니다.

my.matrix <- Matrix(my.matrix)

Matrix 패키지에는 일반 매트릭스처럼 정확하게 사용할 수있는 데이터 형식이 포함되어 있지만 (다른 코드를 변경할 필요는 없지만) 메모리에로드되거나 디스크에 저장되는지에 상관없이 스파 스 데이터를 훨씬 더 효율적으로 저장할 수 있습니다.

또한 내가받는 원시 파일은 각 데이터 포인트에 변수가있는 '긴'형식 x, y, z, i입니다. x * y * zvariable 만 사용 하여 데이터를 차원 배열 로 변환하는 것이 훨씬 더 효율적 i입니다.

데이터를 알고 약간의 상식을 사용하십시오.


무거운 중간 계산이 필요한 개체를 처리하기위한 팁 : 많은 계산 및 중간 단계를 필요로하는 개체를 사용하여 개체를 만드는 경우에는 개체를 만드는 함수와 함께 코드를 작성하고 별도의 청크를 작성하는 것이 유용한 경우가 많습니다. 객체를 생성하고 rmd파일 로 저장 하거나 rmd이미 저장 파일 에서 외부로로드 할 수 있는 옵션을 제공합니다 . R Markdown다음 코드 청크 구조 사용하면 특히 쉽습니다 .

```{r Create OBJECT}

COMPLICATED.FUNCTION <- function(...) { Do heavy calculations needing lots of memory;
                                        Output OBJECT; }

```
```{r Generate or load OBJECT}

LOAD <- TRUE;
#NOTE: Set LOAD to TRUE if you want to load saved file
#NOTE: Set LOAD to FALSE if you want to generate and save

if(LOAD == TRUE) { OBJECT <- readRDS(file = 'MySavedObject.rds'); } else
                 { OBJECT <- COMPLICATED.FUNCTION(x, y, z);
                             saveRDS(file = 'MySavedObject.rds', object = OBJECT); }

```

이 코드 구조를 LOAD사용하면 객체 생성 및 저장 여부에 따라 변경 하거나 기존 저장된 파일에서 직접로드하기 만하면됩니다. (물론, 나는 그것을 생성하고 처음으로 저장해야하지만,이 후에는로드 할 수있는 옵션이 있습니다.) 설정 LOAD = TRUE은 복잡한 기능의 사용을 무시하고 그 안에 무거운 계산을 모두 피합니다. 이 방법은 여전히 ​​관심 객체를 저장하기에 충분한 메모리를 필요로하지만 코드를 실행할 때마다 계산할 필요가 없습니다. 중간 단계를 많이 계산해야하는 개체 (예 : 큰 배열에 대한 루프 관련 계산)의 경우 상당한 시간과 계산을 절약 할 수 있습니다.


knitr를 사용하고 Rmd chuncks에 스크립트를 넣는 것도 도움이됩니다.

일반적으로 코드를 다른 청크로 나누고 검사 점을 캐시 또는 RDS 파일에 저장할 코드를 선택하고

거기에서 "캐시"에 저장되도록 청크를 설정하거나 특정 청크의 실행 여부를 결정할 수 있습니다. 이러한 방식으로 첫 번째 실행에서는 "파트 1"만 처리하고 다른 실행은 "파트 2"만 선택할 수 있습니다.

예:

part1
```{r corpus, warning=FALSE, cache=TRUE, message=FALSE, eval=TRUE}
corpusTw <- corpus(twitter)  # build the corpus
```
part2
```{r trigrams, warning=FALSE, cache=TRUE, message=FALSE, eval=FALSE}
dfmTw <- dfm(corpusTw, verbose=TRUE, removeTwitter=TRUE, ngrams=3)
```

부작용으로 재현성 측면에서 두통을 줄일 수 있습니다. :)


@ Dirk와 @Tony의 답변을 바탕으로 약간의 업데이트를했습니다. 결과는 [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()

달리는

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

때때로 R은 사용되지 않지만 여전히 해제되지 않은 메모리를 해제하는 데 도움이됩니다.


중간 단계가 많은 대형 프로젝트에서 작업 할 때 객체의 양을 작게 유지하려고합니다. 따라서 많은 고유 한 객체를 만드는 대신

dataframe-> step1-> step2-> step3->result

raster-> multipliedRast-> meanRastF-> sqrtRast->resultRast

내가 호출하는 임시 개체로 작업합니다 temp.

dataframe-> temp-> temp-> temp->result

중간 파일이 적고 개요가 더 좋습니다.

raster  <- raster('file.tif')
temp <- raster * 10
temp <- mean(temp)
resultRast <- sqrt(temp)

더 많은 메모리를 절약하기 위해 더 temp이상 필요 없을 때 간단히 제거 수 있습니다 .

rm(temp)

나는 몇 가지 중간 파일이 필요하면, 내가 사용 temp1, temp2, temp3.

내가 사용하는 테스트를 위해 test, test2...

참고 URL : https://stackoverflow.com/questions/1358003/tricks-to-manage-the-available-memory-in-an-r-session



반응형