계산 효율을 높이기 위한 foreach 패키지
패키지 {foreach}는 RevolutionR의 일부로 제공되는 모듈이다. 공짜로 설치해서 사용할 수 있고, {parallel} 보다 훨씬 더 편하기 때문에 대량 계산을 위한 필수품이다.
> install.packages("foreach")
#사용
> library(foreach)
# foreach() 안에 반복할 인수를 벡터로 넣는다. 이들은 sqrt()에 사용된다.
# %do% 연산자가 foreach()와 sqrt()를 연결한다.
> x <- foreach(i=1:3) %do% sqrt(i)
> x
[[1]]
[1] 1
[[2]]
[1] 1.414214
[[3]]
[1] 1.732051
> x <- foreach(i=1:3, .combine='c') %do% sqrt(i)
> x
[1] 1.000000 1.414214 1.732051
# 함수의 정의를 { }안에 직접 작성할 수 있다.
> x <- foreach(i=1:10, j=2:11, .combine='c') %do% {
+ i+j*2
+ }
> x
[1] 5 8 11 14 17 20 23 26 29 32
이것을 c 코드로 쓰면
#include <stdlib.h>
int i=0;
int j=0;
int *x;
int sizeOfArray=10
x=(int *) malloc(sizeOfArray*sizeof(int));
for(i=1; i<11; i++) {
for(j=2; j<12; j++) {
x[i-1] = i+j*2
}
}
...
등등등
-_-;;
가장 쉬운 파이썬 코드로 써도
x=list()
x_append = x.append
for i in range(1,11):
for j in range(2,12):
x_append(i+j*2)
R의 foreach가 더 짧고 더 이해하기 쉽다.
# 결과물이 matrix 데이터로 출력된다.
> x <- foreach(i=1:4, j=2:5, .combine='cbind') %do% {
+ rnorm(5,i,j)
+ }
> x
result.1 result.2 result.3 result.4
[1,] 4.8752530 9.023916 7.4250786 6.266347
[2,] 0.4542793 5.595219 2.8839645 13.681196
[3,] 0.4540102 -1.601676 -1.4208312 2.008794
[4,] 1.8348153 4.766759 -0.7042314 2.664544
[5,] 1.3137413 4.400959 1.5666548 6.405306
# 데이터프레임으로 고치려면
> x.df <- data.frame(x)
> x <- foreach(i=1:4, j=2:5, .combine='+') %do% {
+ rnorm(5,i,j)
+ }
> x
[1] 11.28218 21.26170 16.86678 16.35755 12.56414
물론 사용자가 집합결과를 정의할 수도 있다. 자세한 내용은 foreach 매뉴얼 참조.
우리가 관심을 가지는 것은 foreach의 병렬처리 기능이다.
이때는 %do% 대신에 %dopar%를 쓴다.
주의할 것은 계산이 어차피 빨리 될 것을 병렬처리한다고 해서 더 빨라지지는 않는다. 오히려 데이터를 이리저리 옮기느라 더 느리다. 계산을 몇 시간에 걸쳐, 몇 일에 걸쳐 수행해야 한다면 병렬처리를 적극 고려해야 한다. 당신의 수명을 연장시켜줄 정도로 답답함에서 벗어나게 한다.
간단한 예를 들어 보자.
Intel Celeron quad core 2.16 GHz 컴퓨터다.
foreach에서 병렬처리를 하려면 {doParallel}이 필요하다. 없다면 일단 설치하자.
> install.packages("doSNOW")
> library(doSNOW)
> worker=makeCluster(4) #core수가 4개일 때
> registerDoSNOW(worker)
> system.time(x <- foreach(i=1:4) %do% rnorm(5000*1000))
user system elapsed
7.61 0.01 7.67
> system.time(x <- foreach(i=1:4) %dopar% rnorm(5000*1000))
user system elapsed
0.81 1.15 5.25
> stopCluster(worker)
elapsed 시간을 비교해보면 7.67초에서 5.25초로 계산 시간이 개선된다. 연산 시간이 길어질 수록 이 차이는 더 커진다.
병철처리를 하면 사용할 패키지를 다 넘겨줘야 한다. 혹시 forach 안에서 사용해야 할 패키지가 있으면 .packages=c('package name', 'package nme') 같은 형식으로 넘겨주자. 또한, 병렬 처리의 경과를 보고 싶으면 progress 패키지를 설치하고,
library(progress)
pb<-progress_bar$new(total=100)
progress=function(n) pb$tick()
foreach(i=1:100,.options.snow=list(progress=progress)) %dopar % {...}
이러한 방식으로 설정하자.
설치와 사용
#설치> install.packages("foreach")
#사용
> library(foreach)
인수 하나, 간단한 함수 그리고 list 출력
# 디폴트는 list로 출력하는 것# foreach() 안에 반복할 인수를 벡터로 넣는다. 이들은 sqrt()에 사용된다.
# %do% 연산자가 foreach()와 sqrt()를 연결한다.
> x <- foreach(i=1:3) %do% sqrt(i)
> x
[[1]]
[1] 1
[[2]]
[1] 1.414214
[[3]]
[1] 1.732051
인수 하나, 간단한 함수 그리고 vector 출력
# .combine 옵션에는 결과를 요약할 함수를 적는다.> x <- foreach(i=1:3, .combine='c') %do% sqrt(i)
> x
[1] 1.000000 1.414214 1.732051
인수 둘, 함수 작성을 그 자리에서
# foreach에 i와 j를 써서# 함수의 정의를 { }안에 직접 작성할 수 있다.
> x <- foreach(i=1:10, j=2:11, .combine='c') %do% {
+ i+j*2
+ }
> x
[1] 5 8 11 14 17 20 23 26 29 32
이것을 c 코드로 쓰면
#include <stdlib.h>
int i=0;
int j=0;
int *x;
int sizeOfArray=10
x=(int *) malloc(sizeOfArray*sizeof(int));
for(i=1; i<11; i++) {
for(j=2; j<12; j++) {
x[i-1] = i+j*2
}
}
...
등등등
-_-;;
가장 쉬운 파이썬 코드로 써도
x=list()
x_append = x.append
for i in range(1,11):
for j in range(2,12):
x_append(i+j*2)
R의 foreach가 더 짧고 더 이해하기 쉽다.
.combine='cbind'
# 결합함수로 cbind를 주고 함수의 return을 vector로 한 경우# 결과물이 matrix 데이터로 출력된다.
> x <- foreach(i=1:4, j=2:5, .combine='cbind') %do% {
+ rnorm(5,i,j)
+ }
> x
result.1 result.2 result.3 result.4
[1,] 4.8752530 9.023916 7.4250786 6.266347
[2,] 0.4542793 5.595219 2.8839645 13.681196
[3,] 0.4540102 -1.601676 -1.4208312 2.008794
[4,] 1.8348153 4.766759 -0.7042314 2.664544
[5,] 1.3137413 4.400959 1.5666548 6.405306
# 데이터프레임으로 고치려면
> x.df <- data.frame(x)
.combine='+'
> x <- foreach(i=1:4, j=2:5, .combine='+') %do% {
+ rnorm(5,i,j)
+ }
> x
[1] 11.28218 21.26170 16.86678 16.35755 12.56414
물론 사용자가 집합결과를 정의할 수도 있다. 자세한 내용은 foreach 매뉴얼 참조.
병렬처리
우리가 관심을 가지는 것은 foreach의 병렬처리 기능이다.
이때는 %do% 대신에 %dopar%를 쓴다.
주의할 것은 계산이 어차피 빨리 될 것을 병렬처리한다고 해서 더 빨라지지는 않는다. 오히려 데이터를 이리저리 옮기느라 더 느리다. 계산을 몇 시간에 걸쳐, 몇 일에 걸쳐 수행해야 한다면 병렬처리를 적극 고려해야 한다. 당신의 수명을 연장시켜줄 정도로 답답함에서 벗어나게 한다.
간단한 예를 들어 보자.
Intel Celeron quad core 2.16 GHz 컴퓨터다.
foreach에서 병렬처리를 하려면 {doParallel}이 필요하다. 없다면 일단 설치하자.
> install.packages("doSNOW")
> library(doSNOW)
> worker=makeCluster(4) #core수가 4개일 때
> registerDoSNOW(worker)
> system.time(x <- foreach(i=1:4) %do% rnorm(5000*1000))
user system elapsed
7.61 0.01 7.67
> system.time(x <- foreach(i=1:4) %dopar% rnorm(5000*1000))
user system elapsed
0.81 1.15 5.25
> stopCluster(worker)
elapsed 시간을 비교해보면 7.67초에서 5.25초로 계산 시간이 개선된다. 연산 시간이 길어질 수록 이 차이는 더 커진다.
병철처리를 하면 사용할 패키지를 다 넘겨줘야 한다. 혹시 forach 안에서 사용해야 할 패키지가 있으면 .packages=c('package name', 'package nme') 같은 형식으로 넘겨주자. 또한, 병렬 처리의 경과를 보고 싶으면 progress 패키지를 설치하고,
library(progress)
pb<-progress_bar$new(total=100)
progress=function(n) pb$tick()
foreach(i=1:100,.options.snow=list(progress=progress)) %dopar % {...}
이러한 방식으로 설정하자.
댓글
댓글 쓰기