특정함수에 대한 시간만 보고싶으면 간단하게 아래와 같이 사용자(user): 시간의 경우 프로그램 코드 자체를 R에서 수행한 시간이다. 시스템(sys): 시간의 경우 운영체제(OS)가 대신 작업을 처리하는데 걸린 시간이다. 예를 들면 경과(elapsed): 시간는 가장 이해하기 쉬운 개념으로 프로그램 시작할 때 시간을 측정해서 끝날 때 종료한 시간 차이이다. 상세 관련 문서 vignette(“gettingstartedParallel”) 코어의 수를 설정 한다. 작업관리자를 보면, 형태의 함수들의 도움말을 살펴보면 이미 단순히 foreach만 사용할 경우 오히려 속도가 느려지는 것을 알 수 있다. doParallel과 같이 이용 코어를 8개로 병렬화 했지만 8배까지는 아니고 2배정도 향상된것 같다. 작업이 끝나면 하지만, foreach값이 return하는 set up worker processes that can complete tasks simultaneously. It does this by including components of the To determine the number of cores your machine has, use the An easy way to get started with the http://www.exegetic.biz/blog/2013/08/the-wonders-of-foreach/병렬화를 통한 연산 성능 향상
성능 측정 방법: system.time과 R profiler
system.time
함수를 이용한다.do.call
과 ldply
의 성능을 비교한 것이다.user
, sys
, elapsed
이 세가지 관점으로 시간을 나타내주게 된다.> ptList <- list(1:100000)
> system.time(do.call(rbind,ptList))
사용자 시스템 elapsed
0 0 0
> system.time(ldply(ptList,rbind))
사용자 시스템 elapsed
0.17 0.00 0.17
save()
또는 load()
함수의 경우 sys 시간이 더 길게 된다. 이는 OS 작업을 통해서 파일 입출력을 수행하기 때문이다.
sys 시간이 크다면 메모리 부족도 의심해 봐야한다. R은 기본적으로 메모리에 모든 오브젝트를 로드하고 처리하므로 만약 메모리가 부족할경우 페이지 폴트가 지속적으로 발생해서 성능저하의 원인이 된다.병렬 프로세싱 (doParallel, Window도 가능)
doMC
는 내부적으로 fork()
를 이용하기 때문에 linux
에서 동작 하게 된다.doParallel
는 윈도우에서 사용 할 수 있는 package
를 의미한다.doParallel
은 내부적으로 multicore
, foreach
, snow
를 사용하기 때문에snow
의 기능인 다수의 머신에 클러스터를 구현하는 기능을 제공하므로 doMC
보다 더 막강하다고 할 수 있다.install.packages("doParallel")
library(doParallel)
프로세스의 수 설정
registerDoParallel(cores=4)
Rscript.exe
가 존재 하는 것을 알 수 있다.plyr의 병렬화
{adl}{adl_}ply
.parallel
옵션이 있다. 이 옵션 값이 TRUE
로 설정 되면registerDoParallel()
을 사용해 설정한 만큼의 프로세스가 동시에 실행되어 데이터를 병렬적으로 처리한다.foreach의 병렬화
for
보다는 apply 계열의 함수가 더 빠르다는 것을 알고 있다.
foreach는 이러한 apply보다 더 빠른 loop연산 함수 이다.
그 이유가 바로 간단한 병렬화를 지원하기 때문이다.foreach()
는 기본적으로 %do
를 사용해 실행할 명령의 블록을 지정해야 한다.
만약 foreach()
에서 블록 내 명령을 병렬로 수행하고자 한다면registerDoParallel()
을 한 뒤 foreach()
에 %do%
대신 %dopar%
를 지정하면 된다.registerDoParallel
로 core 수를 결정하면 실행 중인 프로세스 목록에 Rscript.exe라는 프로세스들이 설정한 코어 갯수 만큼 생성된것을 알 수 있다. 반복적으로registerDoParallel
을 실행하면 해당 프로세스가 계속해서 늘어나기 때문에 이를 막기 위해서 명시적으로 stopImplicitCluster()
를 해주는 것이 좋다.R-session
을 종료하면 자동으로 정리해 주긴 하지만 말이다.foreach
는 apply()계열의 함수와 for()를 대체할 수 있는 루프문을 위한 함수 이다.
for문과의 가장 큰 차이는 반환 값이 있다는 점이다. 또한 {}가 아닌 %do%
문을 사용해 블록을 지정한다는 점이다.foreach::foreach(
... # 표현식 ex에 넘겨줄 인자
# .combine은 ex에서의 반환 값을 어떻게 합칠지 지정한다. cbind(컬럼 방향으로 합친 데이터 프레임 반환),
# rbind(행 방향으로 합친 데이터 프레임 반환), c(벡터로 반환) 등이 그예다. 기본값은 결과를 리스트로 합친다.
.combine
%do% ex # ex는 평가할 표현식
)
system.time(l1 <- rnorm(10000000))
library(foreach)
system.time(l2 <- foreach(i=1:4, .combine = 'c')
%do% rnorm(2500000))
> system.time(l1 <- rnorm(10000000))
사용자 시스템 elapsed
0.75 0.00 0.75
>
> library(foreach)
> system.time(l2 <- foreach(i=1:4, .combine = 'c')
+ %do% rnorm(2500000))
사용자 시스템 elapsed
0.78 0.00 0.78
좀더 차이를 주기위해서 이전 예제보다 10대 갯수를 증가 시켰다.> system.time(l1 <- rnorm(100000000))
사용자 시스템 elapsed
7.38 0.14 7.55
>
> library(foreach)
> system.time(l2 <- foreach(i=1:4, .combine = 'c')
+ %do% rnorm(25000000))
사용자 시스템 elapsed
8.28 0.28 8.58
> library(doParallel)
> registerDoParallel(cores = 8)
> system.time(l3p <- foreach(i=1:10, .combine = 'c')
+ %dopar% rnorm(10000000))
사용자 시스템 elapsed
1.54 2.25 5.15
> stopImplicitCluster()
> length(l1)
[1] 100000000
> length(l2)
[1] 100000000
> length(l3p)
[1] 100000000
데이터 분할 및 병합 overhead 때문에 발생하는 통상의 문제이다.
또한 i7-processor 특징상 물리적으로는 4-cores 지만 HT기술을 고려해서 논리적으론 8개로 잡았다.stopImplicitCluster()
를 실행해서 closing doParallel
cluster를 수행 시켜 주자.stopImplicitCluster()
을 수행할경우 apply()
계열의 함수들이 connection error가 발생 하므로
모든 작업이 끝난 다음에 한번만 호출해 주자.foreach 기타 옵션들
list/data.frame
에 이름을 부여하고 싶을 경우.final = function(x) setName(x, names(foo))
를 이용한다..final
은 마지막에 한번만 호출되게 된다.foo <- list(a = 1, b = 2)
bar <- foreach (x = foo, .final = function(x) setNames(x, names(foo))) %do% {
x * 2
}
병렬 프로세싱 (Parallel package, Linux 전용)
multicore
and snow
packages, each taking a different approach towards multitasking.detectCores()
function as follows.multicore
functionality is to use themclappy()
function, which is a parallel version of lapply()
.mclapply {parallel}
mclapply(X, FUN, ..., mc.preschedule = TRUE, mc.set.seed = TRUE,
mc.silent = FALSE, mc.cores = 1L,
mc.cleanup = TRUE, mc.allow.recursive = TRUE)
참고자료
'AI > R Basic' 카테고리의 다른 글
테스트 주도의 개발을 위한 Unit Test in R (0) | 2016.08.19 |
---|---|
Missing Value (0) | 2016.03.20 |
위도,경도를 주소로 변환 ggmap package를 이용한 (geocoding and revgeocode in R) (0) | 2016.03.03 |
Do.call() (0) | 2016.02.05 |
날짜 시간 변환 (Date-Time Conversion Function in R) (0) | 2015.12.14 |