R window 환경에서 CPU를 활용한 foreach 병렬 작업하는 방법

choyunjeong·2025년 1월 11일

1. 패키지 로드

setwd("")

library(doParallel)

library(doRNG)
  • setwd():

    • 우선 작업 경로를 설정합니다.
  • library(doParallel):

    • doParallel 패키지는 foreach 패키지를 위한 "병렬 백엔드 (parallel backend)"이며, 이는 foreach 반복문을 병렬로 실행하는데 필요한 메커니즘을 제공합니다.
    • foreach 패키지로 코드 실행을 병렬화하려면 반드시 doParallel과 같은 패키지와 함께 사용해야 합니다. 사용자가 doParallel 패키지를 로드하지 않으면 foreach는 %dopar% 연산자를 사용하더라도 작업을 순차적 (직렬)으로 실행합니다.
  • library(doRNG)

    • %dorng%%dopar%과 달리 병렬 작업에서 재현 가능한 난수 생성을 지원하므로 동일한 결과를 도출해야 하는 (병렬) 시뮬레이션 작업을 할 수 있습니다.

\\[40pt]

2. 병렬 환경 설정

nCores <- min(parallel::detectCores(), 8)

options(cores = nCores)

doParallel::registerDoParallel(cores = nCores)

source(".R")
  • parallel::detectCores()

    • 사용 가능한 CPU 코어 수를 자동으로 감지.
  • options(cores = nCores):

    • 이전에 정의한 코어수를 기본 코어수로 고정.
  • doParallel::registerDoParallel(cores = nCores)

    • library(doParallel) 패키지 설명에서 library(doParallel)를 로드하지 않으면 foreach 함수는 %dopar% 연산자를 사용하더라도 병렬 작업을 못한다고 설명하였습니다.

    • 추가로 library(doParallel)를 로드하는 것만으로는 충분하지 않으며, registerDoParallel 함수를 호출하여 병렬 백엔드를 로드해야 foreach가 병렬로 작업을 실행할 수 있습니다. doParallel을 단순히 로드한다고 해서 자동으로 병렬 처리가 이루어지는 것은 아닙니다.

  • source(".R")

    • 외부 스크립트 파일에 저장된 코드를 실행하기 위해 사용됩니다. 이를 통해 한 파일에 저장된 R 코드를 현재 작업 공간에서 실행하거나 가져올 수 있습니다.

\\[40pt]

2.1 수동 클러스터 생성

  • doParallel::registerDoParallel(cores = nCores): 이 방법은 R 내부에서 자동적으로 클러스터를 생성할 수 있습니다. 다만 외부 스크립트에 패키지를 로드할 일이 있을 때 잘 호환되지 않을 수 있으므로
foreach(, .packages = c())

와 같이 foreach문 안에 추가적으로 .packages = c() 패키지를 로드 해줘야 합니다. 하지만 로드 해줘야 할 패키지가 너무 많을 때 복잡할 수 있으므로 다음과 같이 클러스트를 직접 생성하는 코드로 작업하면 됩니다.

cl <- parallel::makeCluster(nCores)

doParallel::registerDoParallel(cl)

parallel::clusterEvalQ(cl, source(".R"))

stopCluster(cl)
  • 자동으로 클러스트를 생성하는 doParallel::registerDoParallel()와의 차이점은 source(".R")함수로 외부 스크립트를 불러오고 싶을 때 parallel::clusterEvalQ(cl, source(".R")) 를 사용해야 합니다.

  • 또한 doParallel::registerDoParallel()는 자동으로 백엔드 클러스터를 관리하므로 작업이 끝나면 클러스터가 자동으로 종료되므로 별도로 stopCluster()를 호출할 필요가 없었지만 수동으로 클러스터를 생성하였을 경우 작업 종료 시 반드시 stopCluster()를 사용하여 백엔드 클러스트를 종료하여야 합니다.

\\[40pt]


참고

0개의 댓글