slurm_apply RefClass 方法中的 RefClass 方法
slurm_apply a RefClass method from within a RefClass method
编辑:rslurm
的新版本使解决方案变得非常简单。请参阅下面我的回答。
对于比预期的 MWE 稍长的时间表示歉意,并且我在提交问题后意识到的标题可能不必要地复杂化。我相信真正的问题是让 RefClass object 的环境进入 rslurm::slurm_apply
.
MWE
这里我定义了一个名为 BankAccount
的玩具参考 class。它有两个字段和两个方法。
这些字段是 transactions
,与帐户关联的所有交易的列表和 suspicion_threshold
银行将调查交易的价值。
这两种方法是 is_suspicious
,它将 transactions
与本地计算机上的 suspicion_threshold
进行比较,以及 is_suspicious_slurm
,它使用 rslurm::slurm_apply
传播许多通过 SLURM 管理的计算机集群调用 is_suspicious
。你可以想象如果有很多事务或者如果 is_suspicious
函数更复杂,这可能是必要的。
所以,这是设置
BankAccount <- setRefClass(
Class = 'BankAccount',
fields = list(
transactions = 'numeric',
suspicion_threshold = 'numeric'
)
)
BankAccount$methods(
is_suspicious = function(start_idx = 1, stop_idx = length(transactions)) {
return(start_idx + which(transactions[start_idx:stop_idx] > suspicion_threshold) - 1)
}
)
BankAccount$methods(
is_suspicious_slurm = function(num_nodes) {
usingMethods(is_suspicious)
t <- length(transactions)
t_per_n <- floor(t/num_nodes)
starts <- seq(from = 1, length.out = num_nodes, by = t_per_n)
stops <- seq(from = t_per_n, length.out = num_nodes, by = t_per_n)
stops[num_nodes] <- t
sjob <- rslurm::slurm_apply(f = is_suspicious,
params = data.frame(start_idx = starts,
stop_idx = stops),
nodes = num_nodes,
add_objects = .self)
results_list <- rslurm::get_slurm_out(slr_job = sjob,
outtype = "raw",
wait = TRUE)
return(unlist(results_list))
}
)
现在,在我的本地机器上我可以 运行:
library(RCexampleforSE)
set.seed(27599)
b <- BankAccount$new()
b$transactions <- rnorm(n = 500)
b$suspicion_threshold <- 2
b$is_suspicious()
b$is_suspicious_slurm(num_nodes = 3)
它按预期工作:
62 103 155 171 182 188 297 398 493 499
如果我运行:
b$is_suspicious_slurm(num_nodes = 3)
我收到一个错误,因为我的个人电脑没有连接到 SLURM 集群。
sh: squeue: command not found
Cannot submit; no SLURM workload manager on path
Submission scripts output in directory _rslurm_13ba46e3c70b0
Error in rslurm::get_slurm_out(slr_job = sjob, outtype = "raw", wait = TRUE):
slr_job has not been submitted
如果我登录到我的大学集群,它使用 SLURM 和 运行 相同的脚本,设置和本地方法就像在我的个人计算机上一样工作。当我 运行:
b$is_suspicious_slurm(num_nodes = 3)
它向集群发送作业,正如所希望的那样:
Submitted batch job 6363868
但是这些作业立即出错,并在 slurm_0.out
、slurm_1.out
和 slurm_2.out
中显示以下错误消息:
Error in attr(, "mayCall") : argument 1 is empty
Execution halted
想法和尝试
我认为这份工作可能需要,但没有 BankAccount
object。所以我尝试将它作为 add_objects
参数传递给 rslurm::slurm_apply
:
sjob <- rslurm::slurm_apply(f = is_suspicious,
params = data.frame(start_idx = starts,
stop_idx = stops),
nodes = num_nodes,
add_objects = .self)
我也在引号和内部 eval()
中尝试过,但都没有用。
如何让 rslurm::slurm_apply
创建的工作人员可以访问 object?
编辑:OP 的 就是您需要知道的全部内容。
add_objects
参数用于传递字符向量,而不是对象本身。然后所有对象都保存在一个 RData 文件中,假设它们可以通过名称找到。理论上,您应该能够在方法定义中使用 add_objects = c('.self')
。
这里的关键是,"assuming they can be found"。一旦发布了 rslurm 包的未决更新(这应该会使发现更成功),我将编辑此 post。
将对象传递到群集节点时要非常小心:它们不会返回。不仅会丢失任何副作用,而且 rslurm 没有实现节点间通信。
还要小心 which
:) 对于不从 1 开始的参数,您的 is_suspicious
方法将是错误的。试试这个版本:
BankAccount$methods(
is_suspicious = function(i = 1:length(transactions)) {
idx <- which(transactions[i] > suspicion_threshold)
i[idx]
}
)
rslurm
的 0.4.0 版本完全解决了这个问题。
定义is_suspicious_slurm()
为:
BankAccount$methods(
is_suspicious_slurm = function(num_nodes) {
usingMethods(is_suspicious)
t <- length(transactions)
t_per_n <- floor(t/num_nodes)
starts <- seq(from = 1, length.out = num_nodes, by = t_per_n)
stops <- seq(from = t_per_n, length.out = num_nodes, by = t_per_n)
stops[num_nodes] <- t
sjob <- rslurm::slurm_apply(f = is_suspicious,
params = data.frame(start_idx = starts,
stop_idx = stops),
nodes = num_nodes)
results_list <- rslurm::get_slurm_out(slr_job = sjob,
outtype = "raw",
wait = TRUE)
return(unlist(results_list))
}
)
唯一的变化是在调用rslurm::slurm_apply
时,没有指定add_objects
参数。不需要指定,因为@Ian pointed out:
"...当 slurm_apply 发送序列化函数时,您根本不需要传递 self,它似乎在封闭环境中同时包含“.self”和 "transactions"。 “
编辑:rslurm
的新版本使解决方案变得非常简单。请参阅下面我的回答。
对于比预期的 MWE 稍长的时间表示歉意,并且我在提交问题后意识到的标题可能不必要地复杂化。我相信真正的问题是让 RefClass object 的环境进入 rslurm::slurm_apply
.
MWE
这里我定义了一个名为 BankAccount
的玩具参考 class。它有两个字段和两个方法。
这些字段是 transactions
,与帐户关联的所有交易的列表和 suspicion_threshold
银行将调查交易的价值。
这两种方法是 is_suspicious
,它将 transactions
与本地计算机上的 suspicion_threshold
进行比较,以及 is_suspicious_slurm
,它使用 rslurm::slurm_apply
传播许多通过 SLURM 管理的计算机集群调用 is_suspicious
。你可以想象如果有很多事务或者如果 is_suspicious
函数更复杂,这可能是必要的。
所以,这是设置
BankAccount <- setRefClass(
Class = 'BankAccount',
fields = list(
transactions = 'numeric',
suspicion_threshold = 'numeric'
)
)
BankAccount$methods(
is_suspicious = function(start_idx = 1, stop_idx = length(transactions)) {
return(start_idx + which(transactions[start_idx:stop_idx] > suspicion_threshold) - 1)
}
)
BankAccount$methods(
is_suspicious_slurm = function(num_nodes) {
usingMethods(is_suspicious)
t <- length(transactions)
t_per_n <- floor(t/num_nodes)
starts <- seq(from = 1, length.out = num_nodes, by = t_per_n)
stops <- seq(from = t_per_n, length.out = num_nodes, by = t_per_n)
stops[num_nodes] <- t
sjob <- rslurm::slurm_apply(f = is_suspicious,
params = data.frame(start_idx = starts,
stop_idx = stops),
nodes = num_nodes,
add_objects = .self)
results_list <- rslurm::get_slurm_out(slr_job = sjob,
outtype = "raw",
wait = TRUE)
return(unlist(results_list))
}
)
现在,在我的本地机器上我可以 运行:
library(RCexampleforSE)
set.seed(27599)
b <- BankAccount$new()
b$transactions <- rnorm(n = 500)
b$suspicion_threshold <- 2
b$is_suspicious()
b$is_suspicious_slurm(num_nodes = 3)
它按预期工作:
62 103 155 171 182 188 297 398 493 499
如果我运行:
b$is_suspicious_slurm(num_nodes = 3)
我收到一个错误,因为我的个人电脑没有连接到 SLURM 集群。
sh: squeue: command not found Cannot submit; no SLURM workload manager on path Submission scripts output in directory _rslurm_13ba46e3c70b0 Error in rslurm::get_slurm_out(slr_job = sjob, outtype = "raw", wait = TRUE): slr_job has not been submitted
如果我登录到我的大学集群,它使用 SLURM 和 运行 相同的脚本,设置和本地方法就像在我的个人计算机上一样工作。当我 运行:
b$is_suspicious_slurm(num_nodes = 3)
它向集群发送作业,正如所希望的那样:
Submitted batch job 6363868
但是这些作业立即出错,并在 slurm_0.out
、slurm_1.out
和 slurm_2.out
中显示以下错误消息:
Error in attr(, "mayCall") : argument 1 is empty Execution halted
想法和尝试
我认为这份工作可能需要,但没有 BankAccount
object。所以我尝试将它作为 add_objects
参数传递给 rslurm::slurm_apply
:
sjob <- rslurm::slurm_apply(f = is_suspicious,
params = data.frame(start_idx = starts,
stop_idx = stops),
nodes = num_nodes,
add_objects = .self)
我也在引号和内部 eval()
中尝试过,但都没有用。
如何让 rslurm::slurm_apply
创建的工作人员可以访问 object?
编辑:OP 的
add_objects
参数用于传递字符向量,而不是对象本身。然后所有对象都保存在一个 RData 文件中,假设它们可以通过名称找到。理论上,您应该能够在方法定义中使用 add_objects = c('.self')
。
这里的关键是,"assuming they can be found"。一旦发布了 rslurm 包的未决更新(这应该会使发现更成功),我将编辑此 post。
将对象传递到群集节点时要非常小心:它们不会返回。不仅会丢失任何副作用,而且 rslurm 没有实现节点间通信。
还要小心 which
:) 对于不从 1 开始的参数,您的 is_suspicious
方法将是错误的。试试这个版本:
BankAccount$methods(
is_suspicious = function(i = 1:length(transactions)) {
idx <- which(transactions[i] > suspicion_threshold)
i[idx]
}
)
rslurm
的 0.4.0 版本完全解决了这个问题。
定义is_suspicious_slurm()
为:
BankAccount$methods(
is_suspicious_slurm = function(num_nodes) {
usingMethods(is_suspicious)
t <- length(transactions)
t_per_n <- floor(t/num_nodes)
starts <- seq(from = 1, length.out = num_nodes, by = t_per_n)
stops <- seq(from = t_per_n, length.out = num_nodes, by = t_per_n)
stops[num_nodes] <- t
sjob <- rslurm::slurm_apply(f = is_suspicious,
params = data.frame(start_idx = starts,
stop_idx = stops),
nodes = num_nodes)
results_list <- rslurm::get_slurm_out(slr_job = sjob,
outtype = "raw",
wait = TRUE)
return(unlist(results_list))
}
)
唯一的变化是在调用rslurm::slurm_apply
时,没有指定add_objects
参数。不需要指定,因为@Ian pointed out:
"...当 slurm_apply 发送序列化函数时,您根本不需要传递 self,它似乎在封闭环境中同时包含“.self”和 "transactions"。 “