향후 패키지의 목적은 사용자가 사용할 수있는 다양한 리소스를 사용하여 R 표현식을 비동기 적으로 평가하는 매우 간단하고 균일 한 방법을 제공하는 것입니다.
프로그래밍에서 미래는 향후 어느 시점에서 사용할 수있는 값 에 대한 추상화입니다. 미래의 상태는 해결되지 않거나 해결 될 수 있습니다. 해결 되 자마자 값을 즉시 사용할 수 있습니다. 미래가 아직 해결되지 않은 상태에서 값이 쿼리되면 미래가 해결 될 때까지 현재 프로세스가 차단 됩니다. 차단하지 않고 미래가 해결되었는지 여부를 확인할 수 있습니다. 미래가 어떻게 그리고 언제 해결 될지 정확히 어떻게 그리고시기는 그것을 평가하는 데 사용되는 전략에 달려 있습니다. 예를 들어, 순차적 전략을 사용하여 미래를 해결할 수 있습니다. 즉, 현재 R 세션에서 해결됩니다. 다른 전략은 예를 들어 현재 기계에서 표현식을 동시에 또는 컴퓨팅 클러스터에서 동시에 평가함으로써 미래를 비동기 적으로 해결하는 것일 수 있습니다.
다음은 선물의 기초가 어떻게 작동하는지 보여주는 예입니다. 먼저 일반 R 코드를 사용하는 다음 코드 스 니펫을 고려하십시오.
> v <- {
+ cat( " Hello world! n " )
+ 3.14
+ }
Hello world !
> v
[ 1 ] 3.14
표현식 값을 변수 v
에 할당하여 작동하고 v
의 값을 인쇄합니다. 또한 v
에 대한 표현이 평가되면 메시지도 인쇄합니다.
대신 선물을 사용하도록 수정 된 동일한 코드 스 니펫은 다음과 같습니다.
> library( future )
> v % <- % {
+ cat( " Hello world! n " )
+ 3.14
+ }
> v
Hello world !
[ 1 ] 3.14
차이는 v
구성되는 방식에 있습니다. 평범한 R을 사용하면 우리는 <-
사용하는 반면 미래는 %<-%
사용합니다. 또 다른 차이점은 미래가 해결 된 후 (중이되지 않음) 및 값이 쿼리 된 후 출력이 전달된다는 것입니다 (Vignette 'Outputting Text'참조).
그렇다면 미래가 왜 유용합니까? 우리는 단순히 설정을 다음과 같이 전환하여 별도의 R 프로세스에서 미래 표현식을 평가할 수 있기 때문입니다.
> library( future )
> plan( multisession )
> v % <- % {
+ cat( " Hello world! n " )
+ 3.14
+ }
> v
Hello world !
[ 1 ] 3.14
비동기 미래를 사용하면 현재/메인 R 프로세스가 차단되지 않으므로 백그라운드에서 실행되는 별도의 프로세스로 미래가 해결되는 동안 추가 처리가 가능합니다. 다시 말해, 선물은 R에서 병렬 및 / 또는 분산 처리를위한 간단하지만 강력한 구성을 제공합니다.
이제 선물에 대한 모든 끔찍한 세부 사항을 읽을 수는 없지만 시도해 보려면 병렬 및 비 평면 평가를 사용하여 Mandelbrot 데모를 사용하여 끝까지 건너 뛰십시오.
선물은 암시 적으로 또는 명시 적으로 만들 수 있습니다. 위의 입문 예에서 우리는 v %<-% { expr }
구조를 통해 생성 된 암시 적 선물을 사용했습니다. 대안은 f <- future({ expr })
및 v <- value(f)
구성을 사용하는 명백한 선물 입니다. 이를 통해 우리의 예제는 대안으로 다음과 같이 작성 될 수 있습니다.
> library( future )
> f <- future({
+ cat( " Hello world! n " )
+ 3.14
+ })
> v <- value( f )
Hello world !
> v
[ 1 ] 3.14
미래의 구성 스타일 중 하나는 똑같이 작동합니다 (*). 암시 적 스타일은 일반 R 코드 작성과 가장 유사합니다. 원칙적으로, 당신이해야 할 일은 <-
%<-%
로 교체하여 과제를 향후 과제로 바꾸는 것입니다. 반면에,이 단순성은 특히 비동기 미래가 사용될 때 속임수 일 수 있습니다. 대조적으로, 명백한 스타일은 선물이 사용되고 있음을 훨씬 더 명확하게하여 실수의 위험을 낮추고 코드를 읽는 다른 사람들에게 디자인을 더 잘 전달합니다.
(*) 일부 (작은) 수정없이 %<-%
사용할 수없는 경우가 있습니다. 우리는이 문서의 끝 근처에서 암시 적 선물을 사용할 때 섹션 '제약 조건에서 이것으로 돌아갑니다.
요약하면, 명백한 미래를 위해 우리는 다음을 사용합니다.
f <- future({ expr })
- 미래를 만듭니다v <- value(f)
- 미래의 가치를 얻습니다 (아직 해결되지 않은 경우 차단)암시 적 선물의 경우 우리는 다음을 사용합니다.
v %<-% { expr }
- 미래와 그 가치에 대한 약속을 만듭니다.간단하게 유지하기 위해이 문서의 나머지 부분에서 암시 적 스타일을 사용하지만 논의 된 모든 것이 명시 적 미래에도 적용됩니다.
향후 패키지는 다음 유형의 선물을 구현합니다.
이름 | OS | 설명 |
---|---|---|
동기 : | 비 임금 : | |
sequential | 모두 | 순차적으로 그리고 현재 R 프로세스에서 |
비동기 : | 평행한 : | |
multisession | 모두 | 배경 R 세션 (현재 기계) |
multicore | Windows/Rstudio가 아닙니다 | 포크 R 프로세스 (현재 기계에서) |
cluster | 모두 | 현재, 로컬 및/또는 원격 기계의 외부 세션 |
향후 패키지는 추가 전략에 대한 지원도 구현할 수 있도록 설계되었습니다. 예를 들어, Future.callr 패키지는 Callr 패키지를 사용하는 백그라운드 R 프로세스에서 선물을 평가하는 미래의 백엔드를 제공합니다. 이들은 multisession
선물과 유사하게 작동하지만 몇 가지 장점이 있습니다. 계속, Future.batchTools 패키지는 BatchTools 패키지가 지원하는 모든 유형의 클러스터 기능 ( "백엔드")에 대한 선물을 제공합니다. 구체적으로, Slurm, Torque/PBS, Oracle/Sun Grid Engine (SGE) 및로드 공유 기능 (LSF)과 같은 작업 스케줄러를 통한 R 표현을 평가하기위한 선물도 제공됩니다.
기본적으로 향후 표현식은 간절히 (= 순간적으로) 동기식으로 평가됩니다 (현재 R 세션에서). 이 평가 전략을 "순차적"이라고합니다. 이 섹션에서는 이러한 각 전략을 거쳐 공통점이 무엇인지, 어떻게 다른지 논의 할 것입니다.
각기 다른 미래 전략을 살펴보기 전에 미래의 API의 목표를 명확히하는 것이 도움이 될 것입니다 (미래 패키지에 의해 정의 된대로). 선물로 프로그래밍 할 때는 코드 실행에 어떤 미래 전략이 사용되는지는 중요하지 않습니다. 이는 사용자가 액세스 할 수있는 계산 리소스를 실제로 알 수 없으므로 평가 전략 선택이 개발자가 아닌 사용자의 손에 달려야합니다. 다시 말해, 코드는 사용 된 선물 유형, 예를 들어 동기식 또는 비동기식에 대해 가정해서는 안됩니다.
미래 API의 설계 중 하나는 모든 유형의 선물이 동일하게 작동하는 것처럼 보이도록 차이를 캡슐화하는 것이 었습니다. 이것은 표현에도 불구하고 현재 R 세션 또는 전 세계의 원격 R 세션에서 로컬로 평가 될 수 있습니다. 다른 유형의 선물들 사이에서 일관된 API와 행동을 갖는 또 다른 명백한 장점은 프로토 타이핑 중에 도움이된다는 것입니다. 일반적으로 스크립트를 구축하는 동안 순차적 평가를 사용하고 나중에 스크립트가 완전히 개발되면 비동기 처리를 켤 수 있습니다.
이 때문에 다른 전략의 기본값은 미래 표현을 평가하는 결과와 부작용이 가능한 한 유사하도록하는 것입니다. 보다 구체적으로, 다음은 모든 미래에 해당됩니다.
모든 평가는 현지 환경 (예 : local({ expr })
)에서 수행되므로 과제가 통화 환경에 영향을 미치지 않도록합니다. 이것은 외부 R 프로세스에서 평가할 때 자연 스럽지만 현재 R 세션에서 평가할 때도 시행됩니다.
미래가 구성되면 글로벌 변수가 식별됩니다 . 비동기 평가를 위해, 글로벌은 미래의 표현을 평가할 R 프로세스/세션으로 내 보냅니다. 게으른 평가 ( lazy = TRUE
)를 가진 순차적 미래의 경우 글로벌은 "냉동"(미래의 지역 환경으로 클로닝)입니다. 또한 실수로 너무 큰 물체를 내보내지 않기 위해 모든 글로벌의 총 크기가 주어진 임계 값보다 적다는 주장이 내장되어 있습니다 (옵션을 통해 제어 가능, cf. help("future.options")
). 임계 값이 초과되면 유익한 오류가 발생합니다.
미래의 표현은 한 번만 평가됩니다 . 값 (또는 오류)이 수집 되 자마자 모든 후속 요청에 대해 사용할 수 있습니다.
다음은 모든 과제가 지역 환경에 수행된다는 것을 보여주는 예입니다.
> plan( sequential )
> a <- 1
> x % <- % {
+ a <- 2
+ 2 * a
+ }
> x
[ 1 ] 4
> a
[ 1 ] 1
이제 우리는 다양한 미래 전략을 탐구 할 준비가되었습니다.
동기 미래는 차례가되고 가장 일반적으로이를 생성하는 R 프로세스에 의해 해결됩니다. 동기식 미래가 해결되면 해결 될 때까지 주요 프로세스를 차단합니다.
달리 지정되지 않는 한 순차적 미래는 기본값입니다. 그들은 미래의 API와 그 행동을 여전히 충족시키면서 정기적 인 R 평가와 가능한 한 비슷한 행동을하도록 설계되었습니다. 다음은 자신의 속성을 설명하는 예입니다.
> plan( sequential )
> pid <- Sys.getpid()
> pid
[ 1 ] 1437557
> a % <- % {
+ pid <- Sys.getpid()
+ cat( " Future 'a' ... n " )
+ 3.14
+ }
> b % <- % {
+ rm( pid )
+ cat( " Future 'b' ... n " )
+ Sys.getpid()
+ }
> c % <- % {
+ cat( " Future 'c' ... n " )
+ 2 * a
+ }
Future ' a ' ...
> b
Future ' b ' ...
[ 1 ] 1437557
> c
Future ' c ' ...
[ 1 ] 6.28
> a
[ 1 ] 3.14
> pid
[ 1 ] 1437557
열렬한 순차적 평가가 진행되고 있기 때문에 세 가지 미래는 각각 생성되는 순간에 즉시 해결됩니다. 또한 현재 프로세스의 프로세스 ID에 할당 된 통화 환경의 pid
덮어 쓰거나 제거되지 않은 방법에 유의하십시오. 이는 미래가 지역 환경에서 평가되기 때문입니다. 동기식 (UNI) 처리가 사용되므로 미래 b
주요 R 프로세스 (여전히 로컬 환경)에 의해 해결되므로 b
와 pid
의 값이 동일합니다.
다음으로, 우리는 백그라운드에서 해결되는 미래 인 비동기 미래로 전환 할 것입니다. 디자인별로, 이러한 선물은 차단하지 않습니다. 즉, 추가 선물 생성을 포함한 다른 작업에 호출 프로세스를 사용할 수 있습니다. 호출 프로세스가 아직 해결되지 않은 미래의 가치에 액세스하려고 시도하거나 모든 사용 가능한 R 프로세스가 다른 미래에 바쁠 때 다른 비동기 미래를 만들려고 할 때만 차단됩니다.
우리는 모든 운영 체제에서 지원되기 때문에 멀티션 선물로 시작합니다. MultiSESSION 미래는 호출 R 프로세스와 동일한 기계에서 실행되는 백그라운드 R 세션에서 평가됩니다. 다중 세션 평가의 예는 다음과 같습니다.
> plan( multisession )
> pid <- Sys.getpid()
> pid
[ 1 ] 1437557
> a % <- % {
+ pid <- Sys.getpid()
+ cat( " Future 'a' ... n " )
+ 3.14
+ }
> b % <- % {
+ rm( pid )
+ cat( " Future 'b' ... n " )
+ Sys.getpid()
+ }
> c % <- % {
+ cat( " Future 'c' ... n " )
+ 2 * a
+ }
Future ' a ' ...
> b
Future ' b ' ...
[ 1 ] 1437616
> c
Future ' c ' ...
[ 1 ] 6.28
> a
[ 1 ] 3.14
> pid
[ 1 ] 1437557
우리가 관찰하는 첫 번째 것은 a
, c
및 pid
의 값이 이전과 동일하다는 것입니다. 그러나 우리는 b
이전과 다르다는 것을 알 수 있습니다. 이는 미래 b
다른 R 프로세스에서 평가되므로 다른 프로세스 ID를 반환하기 때문입니다.
멀티션 평가가 사용될 때, 패키지는 배경에서 표현을 생성 할 때 표현을 평가함으로써 멀티션 미래에 서비스를 제공하는 일련의 R 세션을 시작합니다. 모든 배경 세션이 다른 미래에 바쁘다면, 다음 멀티 세션 미래의 생성은 백그라운드 세션이 다시 제공 될 때까지 차단 됩니다. 출시 된 총 배경 프로세스의 총 수는 availableCores()
의 값에 따라 결정됩니다.
> availableCores()
mc.cores
2
이 특정 결과는 mc.cores
옵션이 주요 프로세스를 포함한 총 2 개의 프로세스에서 사용할 수 있도록 설정되었음을 알 수 있습니다. 다시 말해, 이러한 설정에서는 멀티션 선물을 제공하는 두 가지 배경 프로세스가 있습니다. availableCores()
는 다른 옵션 및 시스템 환경 변수에 민첩합니다. 예를 들어, 컴퓨팅 클러스터 스케줄러가 사용되는 경우 (예 : 토크/PBS 및 SLURM) 주어진 작업에 할당 된 코어 수를 지정하는 특정 환경 변수를 설정합니다. availableCores()
이것을 인정합니다. 다른 것이 지정되지 않으면 기계의 사용 가능한 모든 코어가 사용됩니다. parallel::detectCores()
. 자세한 내용은 help("availableCores", package = "parallelly")
참조하십시오.
R이 기본적으로 Windows를 제외한 모든 운영 체제 인 프로세스 포킹을 지원하는 운영 체제에서는 백그라운드에서 R 세션을 산란하는 대안입니다. 멀티 코어 선물을 사용하려면 지원할 때 다음을 지정하십시오.
plan( multicore )
다중 세션 선물과 마찬가지로, 실행 중 최대 병렬 프로세스 수는 availableCores()
에 의해 결정됩니다. 두 경우 모두 로컬 시스템에서 평가가 수행되므로.
R 프로세스를 포킹하는 것은 백그라운드에서 실행되는 별도의 R 세션으로 작업하는 것보다 빠를 수 있습니다. 한 가지 이유는 큰 글로벌을 배경 세션으로 내보내는 오버 헤드가 포킹과 공유 메모리가 사용될 때보 다 커질 수 있기 때문입니다. 반면, 공유 메모리는 읽는다 . 이는 포크 프로세스 중 하나 ( "작업자")에 의해 공유 객체에 대한 수정이 운영 체제의 사본을 유발한다는 것을 의미한다. 이것은 R 쓰레기 수집기가 포크 프로세스 중 하나에서 실행될 때 발생할 수 있습니다.
반면에, 프로세스 포킹은 일부 R 환경에서도 불안정한 것으로 간주됩니다. 예를 들어, rstudio 프로세스 내에서 R을 실행할 때 Forking이 충돌 한 R 세션이 발생할 수 있습니다. 이로 인해 향후 패키지는 Rstudio에서 실행할 때 기본적으로 멀티 코어 미래를 비활성화합니다. 자세한 내용은 help("supportsMulticore")
참조하십시오.
클러스터 선물은 임시 클러스터의 표현식을 평가합니다 (병렬 패키지에 의해 구현). 예를 들어, 3 개의 노드 n1
, n2
및 n3
에 액세스 할 수 있다고 가정하면 다음과 같은 비동기 평가에이를 사용할 수 있습니다.
> plan( cluster , workers = c( " n1 " , " n2 " , " n3 " ))
> pid <- Sys.getpid()
> pid
[ 1 ] 1437557
> a % <- % {
+ pid <- Sys.getpid()
+ cat( " Future 'a' ... n " )
+ 3.14
+ }
> b % <- % {
+ rm( pid )
+ cat( " Future 'b' ... n " )
+ Sys.getpid()
+ }
> c % <- % {
+ cat( " Future 'c' ... n " )
+ 2 * a
+ }
Future ' a ' ...
> b
Future ' b ' ...
[ 1 ] 1437715
> c
Future ' c ' ...
[ 1 ] 6.28
> a
[ 1 ] 3.14
> pid
[ 1 ] 1437557
parallel::makeCluster()
생성하는 모든 유형의 클러스터는 클러스터 선물에 사용할 수 있습니다. 예를 들어, 위의 클러스터는 다음과 같이 명시 적으로 설정할 수 있습니다.
cl <- parallel :: makeCluster(c( " n1 " , " n2 " , " n3 " ))
plan( cluster , workers = cl )
또한 parallel::stopCluster(cl)
CL이 더 이상 필요하지 않을 때 클러스터 cl
종료하는 것이 좋은 스타일로 간주됩니다. 그러나 기본 프로세스가 종료되면 자체적으로 종료됩니다. 이러한 클러스터를 설정하고 관리하는 방법에 대한 자세한 내용은 help("makeCluster", package = "parallel")
참조하십시오. hosts
문자 인 벡터 인 경우 plan(cluster, workers = hosts)
사용하여 암시 적으로 생성 된 클러스터는 메인 R 세션이 종료되거나 미래 전략이 변경 될 때 (예 : 전화 plan(sequential)
를 통해 종료됩니다.
자동 인증 설정 (예 : SSH 키 쌍)을 사용하면 원격 시스템 클러스터를 사용하는 데 동일한 접근 방식을 사용하지 못하게하는 것은 없습니다.
각 노드에서 여러 작업자를 실행하려면 해당 노드에서 실행할 작업자 수만큼 노드 이름을 여러 번 복제하십시오. 예를 들어,
> plan(cluster, workers = c(rep("n1", times = 3), "n2", rep("n3", times = 5)))
n1
에서 3 명의 근로자, n2
에 1 명, n3
에서 5 명은 총 9 명의 평행 근로자로 운영됩니다.
지금까지 우리는 선물의 "평평한 토폴로지"라고 할 수있는 것을 논의했습니다. 즉, 모든 미래는 동일한 환경에 만들어져 배정됩니다. 그러나 우리가 선물의 "중첩 된 토폴로지"를 사용하는 것을 막는 것은 아무것도 없으며, 한 세트의 선물이 내부적으로 다른 미래 세트를 만들 수 있습니다.
예를 들어, 다음은 멀티션 평가를 사용하고 두 번째 미래 ( b
)가 두 가지 내부 미래를 사용하는 두 가지 "최고"선물 ( a
및 b
)의 예입니다.
> plan( multisession )
> pid <- Sys.getpid()
> a % <- % {
+ cat( " Future 'a' ... n " )
+ Sys.getpid()
+ }
> b % <- % {
+ cat( " Future 'b' ... n " )
+ b1 % <- % {
+ cat( " Future 'b1' ... n " )
+ Sys.getpid()
+ }
+ b2 % <- % {
+ cat( " Future 'b2' ... n " )
+ Sys.getpid()
+ }
+ c( b.pid = Sys.getpid(), b1.pid = b1 , b2.pid = b2 )
+ }
> pid
[ 1 ] 1437557
> a
Future ' a ' ...
[ 1 ] 1437804
> b
Future ' b ' ...
Future ' b1 ' ...
Future ' b2 ' ...
b.pid b1.pid b2.pid
1437805 1437805 1437805
프로세스 ID를 검사함으로써, 우리는 미래를 해결하기위한 총 세 가지 프로세스가 있음을 알 수 있습니다. 주요 R 프로세스 (PID 1437557)가 있으며 a
(PID 1437804)와 b
(PID 1437805)가 사용하는 두 가지 프로세스가 있습니다. 그러나 b
에 의해 중첩 된 두 미래 ( b1
및 b2
)는 b
와 동일한 R 공정으로 평가됩니다. 중첩 선물은 달리 명시되지 않는 한 순차적 평가를 사용하기 때문입니다. 몇 가지 이유가 있지만 주된 이유는 재귀적인 전화를 통해 실수로 많은 백그라운드 프로세스를 때리는 것을 방지하기 때문입니다.
다중 세션 평가 에 의해 해결되는 첫 번째 수준의 선물 수준과 순차적 평가에 의해 두 번째 수준을 제외하고, 우리는 plan()
에 대한 평가 전략 목록을 제공 할 수 있습니다. 첫째, 위와 동일한 평가 전략은 다음과 같이 명시 적으로 지정할 수 있습니다.
plan( list ( multisession , sequential ))
여러 수준의 멀티션 평가를 시도하면 실제로 동일한 동작을 얻을 수 있습니다.
> plan( list ( multisession , multisession ))
[ ... ]
> pid
[ 1 ] 1437557
> a
Future ' a ' ...
[ 1 ] 1437901
> b
Future ' b ' ...
Future ' b1 ' ...
Future ' b2 ' ...
b.pid b1.pid b2.pid
1437902 1437902 1437902
그 이유는 여기에서 우리가 기계가 지원할 수있는 것보다 더 많은 프로세스를 시작하지 않도록 보호하기 때문입니다. 내부적으로, 이것은 mc.cores = 1
설정하여 수행되므로 parallel::mclapply()
와 같은 함수가 순차적으로 실행되기 위해 다시 떨어집니다. 다중 세션 및 멀티 코어 평가의 경우입니다.
계속해서, 순차적 평가로 시작한 다음 중첩 된 선물에 대해 다중 세션 평가를 사용하면 다음을 얻습니다.
> plan( list ( sequential , multisession ))
[ ... ]
> pid
[ 1 ] 1437557
> a
Future ' a ' ...
[ 1 ] 1437557
> b
Future ' b ' ...
Future ' b1 ' ...
Future ' b2 ' ...
b.pid b1.pid b2.pid
1437557 1438017 1438016
이는 a
와 b
호출 프로세스 (PID 1437557)에서 해결 된 반면, 두 개의 중첩 선물 ( b1
및 b2
)은 두 개의 개별 R 프로세스 (PIDS 1438017 및 1438016)로 해결된다는 것을 분명히 보여줍니다.
이것을 말하면, 각 레벨에서 사용 가능한 코어 수를 명시 적 으로 지정하는 경우 중첩 된 멀티션 평가 전략을 사용하는 것이 실제로 가능합니다. 이를 위해서는 기본 설정을 "조정"해야하며 다음과 같이 수행 할 수 있습니다.
> plan( list (tweak( multisession , workers = 2 ), tweak( multisession ,
+ workers = 2 )))
[ ... ]
> pid
[ 1 ] 1437557
> a
Future ' a ' ...
[ 1 ] 1438105
> b
Future ' b ' ...
Future ' b1 ' ...
Future ' b2 ' ...
b.pid b1.pid b2.pid
1438106 1438211 1438212
먼저, 우리는 a
와 b
가 호출 프로세스 (PID 1437557)와 다른 프로세스 (PID 1438105 및 1438106)에서 해결된다는 것을 알 수 있습니다. 둘째, 두 개의 중첩 선물 ( b1
및 b2
)은 아직 두 개의 다른 R 프로세스 (PIDS 1438211 및 1438212)에서 해결됩니다.
각 수준에서 중첩 선물 및 다양한 평가 전략 작업에 대한 자세한 내용은 'R : Future Topologies'의 Vignette 'Futures'를 참조하십시오.
차단하지 않고 미래가 해결되었는지 여부를 확인할 수 있습니다. 이것은 resolved(f)
함수를 사용하여 수행 할 수 있으며, 이는 명시 적 미래 f
입력으로 취합니다. 우리가 암시 적 선물 (위의 모든 예에서와 같이)과 함께 일하는 경우 f <- futureOf(a)
미래를 암시 적 미래에서 검색 할 수 있습니다. 예를 들어,
> plan( multisession )
> a % <- % {
+ cat( " Future 'a' ... " )
+ Sys.sleep( 2 )
+ cat( " done n " )
+ Sys.getpid()
+ }
> cat( " Waiting for 'a' to be resolved ... n " )
Waiting for ' a ' to be resolved ...
> f <- futureOf( a )
> count <- 1
> while ( ! resolved( f )) {
+ cat( count , " n " )
+ Sys.sleep( 0.2 )
+ count <- count + 1
+ }
1
2
3
4
5
6
7
8
9
10
> cat( " Waiting for 'a' to be resolved ... DONE n " )
Waiting for ' a ' to be resolved ... DONE
> a
Future ' a ' ... done
[ 1 ] 1438287
때때로 미래는 당신이 기대했던 것이 아닙니다. 미래를 평가하는 동안 오류가 발생하면 오류가 전파되고 미래의 값이 요청 될 때 호출 환경에서 오류로 던져집니다. 예를 들어, 오류가 발생하는 미래에 게으른 평가를 사용하는 경우
> plan( sequential )
> b <- " hello "
> a % <- % {
+ cat( " Future 'a' ... n " )
+ log( b )
+ } % lazy % TRUE
> cat( " Everything is still ok although we have created a future that will fail. n " )
Everything is still ok although we have created a future that will fail.
> a
Future ' a ' ...
Error in log( b ) : non - numeric argument to mathematical function
값이 요청 될 때마다 오류가 발생합니다. 즉, 값을 다시 얻으려고하면 동일한 오류 (및 출력)가 생성됩니다.
> a
Future ' a ' ...
Error in log( b ) : non - numeric argument to mathematical function
In addition : Warning message :
restarting interrupted promise evaluation
오류가 발생한 통화 스택의 마지막 통화를 보려면 향후 backtrace()
함수 (*)를 사용할 수 있습니다.
> backtrace( a )
[[ 1 ]]
log( a )
(*) 일반적으로 사용되는 traceback()
선물의 맥락에서 관련 정보를 제공하지 않습니다. 또한 불행히도 오류가 발생한 통화 목록 (평가 된 표현)을 볼 수 없습니다. 오류를 준 호출 만 (내부적으로 사용한 tryCatch()
의 제한 때문입니다).
R 표현이 비동기 적으로 평가되거나 게으른 평가를 통해 순차적으로 평가 될 때마다, 글로벌 (일명 "자유") 물체를 식별하고 평가자에게 전달해야합니다. 게으른 평가를 위해서는 글로벌이 생성 될 때와 해결 시점 사이에 전 세계가 변할 수 있기 때문에 미래가 창조 될 때와 정확히 전달되어야합니다. 비동기 처리의 경우 글로벌이 식별 해야하는 이유는 미래를 평가하는 프로세스로 내보낼 수 있기 때문입니다.
향후 패키지는 이러한 작업을 가능한 한 자동화하려고합니다. 정적 코드 검사를 사용하여 글로벌 변수를 식별하는 Globals 패키지의 도움으로이를 수행합니다. 글로벌 변수가 식별되면 캡처되어 평가 프로세스에 사용할 수 있습니다. 또한 글로벌이 패키지로 정의되면 해당 글로벌이 내보내지 않습니다. 대신, 미래를 평가할 때 해당 패키지가 첨부되어 있는지 확인합니다. 이는 메인 R 세션의 설정을 더 잘 반영 할뿐만 아니라 특히 원격 컴퓨팅 노드를 사용할 때 메모리뿐만 아니라 시간 및 대역폭을 절약하는 글로벌 내보내기의 필요성을 최소화합니다.
마지막으로, 정적 코드 검사에서만 글로벌을 식별하는 것은 어려운 문제라는 것을 명확히해야합니다. 글로벌의 자동 식별이 실패하는 코너 사례가 항상있어 오 탐지가 식별되거나 일부 글로벌이 누락되거나 런타임 오류가 발생하거나 잘못된 결과를 초래할 수 있습니다). Vignette의 R : Solutions의 일반적인 문제 '는 일반적인 사례의 예를 제공하고이를 피하는 방법과 패키지가 글로벌을 식별하거나 거짓으로 식별 된 글로벌을 무시하는 방법을 설명합니다. 충분하지 않은 경우, 이름으로 글로벌 변수를 수동으로 지정할 수 있습니다 (예 : globals = c("a", "slow_sum")
) 또는 이름 -Value 쌍 (예 : globals = list(a = 42, slow_sum = my_sum)
).
명시 적 미래에는 존재하지 않는 암시 적 선물에는 한 가지 제한이 있습니다. 명백한 미래는 r의 다른 물체와 마찬가지로 어디서나 할당 할 수 있습니다. 예를 들어, 우리는 루프로 몇 가지를 만들어 목록에 할당 할 수 있습니다 (예 :
> plan( multisession )
> f <- list ()
> for ( ii in 1 : 3 ) {
+ f [[ ii ]] <- future({
+ Sys.getpid()
+ })
+ }
> v <- lapply( f , FUN = value )
> str( v )
List of 3
$ : int 1438377
$ : int 1438378
$ : int 1438377
암시 적 선물을 사용할 때는 불가능 합니다. 이는 일반 <-
연산자를 사용할 수있는 모든 경우에 %<-%
할당 연산자를 사용할 수 없기 때문입니다. assign(name, value, envir)
작동하는 방식과 매우 유사한 환경 (통화 환경 포함)에 미래의 값을 할당하는 데만 사용될 수 있습니다. 그러나 우리는 명명 된 지수를 사용하여 환경에 암시 적 선물을 할당 할 수 있습니다.
> plan( multisession )
> v <- new.env()
> for ( name in c( " a " , " b " , " c " )) {
+ v [[ name ]] % <- % {
+ Sys.getpid()
+ }
+ }
> v <- as.list( v )
> str( v )
List of 3
$ a : int 1438485
$ b : int 1438486
$ c : int 1438485
여기서는 as.list(v)
환경 v
의 모든 선물이 해결 될 때까지 블록. 그런 다음 해당 값이 수집되어 일반 목록으로 반환됩니다.
숫자 지수가 필요한 경우 목록 환경을 사용할 수 있습니다. ListenV 패키지에서 구현 된 목록 환경은 사용자 지정된 서브 세트 연산자가있는 정기적 인 환경으로 목록을 색인화하는 방법과 매우 유사하게 색인화 할 수 있습니다. 목록을 사용하는 목록 환경을 사용하면 숫자 지수를 사용하여 암시 적 선물을 목록과 같은 개체에 할당 할 수도 있습니다. 예를 들어,
> library( listenv )
> plan( multisession )
> v <- listenv()
> for ( ii in 1 : 3 ) {
+ v [[ ii ]] % <- % {
+ Sys.getpid()
+ }
+ }
> v <- as.list( v )
> str( v )
List of 3
$ : int 1438582
$ : int 1438583
$ : int 1438582
이전과 마찬가지로, as.list(v)
블록이 모든 선물이 해결 될 때까지 블록.
다양한 유형의 선물이 어떻게 평가되는지 살아있는 그림을 보려면이 패키지의 Mandelbrot 데모를 실행하십시오. 먼저 순차적 평가를 시도하고
library( future )
plan( sequential )
demo( " mandelbrot " , package = " future " , ask = FALSE )
선물이 사용되지 않으면 스크립트가 어떻게 실행되는지와 비슷합니다. 그런 다음 백그라운드에서 실행되는 병렬 R 프로세스를 사용하여 다른 Mandelbrot 평면을 계산하는 다중 세션 평가를 시도하십시오. 노력하다,
plan( multisession )
demo( " mandelbrot " , package = " future " , ask = FALSE )
마지막으로 여러 기계에 액세스 할 수있는 경우 작업자 클러스터를 설정하여 사용할 수 있습니다.
plan( cluster , workers = c( " n2 " , " n5 " , " n6 " , " n6 " , " n9 " ))
demo( " mandelbrot " , package = " future " , ask = FALSE )
R 패키지 미래는 CRAN에서 사용할 수 있으며 r로 설치할 수 있습니다.
install.packages( " future " )
GitHub에서 개발할 수있는 프리 릴리스 버전을 설치하려면 GitHub에서 develop
하십시오.
remotes :: install_github( " futureverse/future " , ref = " develop " )
이것은 소스에서 패키지를 설치합니다.
이 패키지에 기여하려면 Contributing.md를 참조하십시오.