R нестандартная оценка: получить значение обещания, оставив его без оценки [или: сохранить внешний указатель действительным...]
Это продолжение функции параллелизации с использованием внешних указателей (XPtr)
Я не буду воспроизводить код Cpp здесь, чтобы сделать вещи короче. Проблема заключалась в том, что после оценки параметра функции он определяется в среде функции и, в случае внешнего указателя, больше не доступен в кластере ветвлений.
Итак, пока эта функция работает:
require(parallel)
test1 <- function(a) {
cl <- makeForkCluster(nnodes=2)
r <- parLapply(cl, 1:5, function(i) g(a,i) )
stopCluster(cl)
unlist(r)
}
Эта функция не:
test2 <- function(a) {
cl <- makeForkCluster(nnodes=2)
p <- g(a, 0)
r <- parLapply(cl, 1:5, function(i) g(a,i) )
stopCluster(cl)
unlist(r)
}
Как отметил Ральф Стубнер, это произошло из-за того, что g(a, 0)
заставил оценку обещания a
, Он предложил следующую работу (здесь с двумя отладочными отпечатками, чтобы понять, как это работает):
test3 <- function(a) {
cl <- makeForkCluster(nnodes = 2)
print(pryr::promise_info(a))
b <- eval(substitute(a))
p <- g(b, 0)
print(pryr::promise_info(a))
r <- parLapply(cl, 1:5, function(i) g(a,i) )
stopCluster(cl)
unlist(r)
}
Это позволило получить доступ к тому, что было в a
, но a
было все еще неоцененным обещанием. Но это не работает, когда test3
вызывается из другой функции!
test4 <- function(b) test1(b)
test5 <- function(b) test3(b)
В то время как test4
работает хорошо (рекурсивная оценка обещания, кажется, дает действительный указатель), обходной путь в test3
больше не работает при вызове из test5
,
Отладочные отпечатки показывают, что несмотря на eval(substitute(a))
Трюк, обещание оценивается. Насколько я понимаю, этот трюк заставляет оценить обещание b
из test5
в его среде, таким образом a
оценивается тоже.
Есть ли другой обходной путь? (Я пытался играть с pryr::parent_promise
но даже код из примера на странице руководства дает странные результаты).
У меня есть другие сложные проблемы этого типа. Общий способ получения содержимого обещания без его оценки или передачи внешних указателей другим функциям с помощью parLapply
Звоните в самом конце, не спотыкаясь постоянно об этой проблеме, было бы очень кстати.