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.outslurm_1.outslurm_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"。 “