循环的顺序对R中的速度有影响吗
我有一个问题,我想运行一个模拟研究,其中模拟取决于两个变量循环的顺序对R中的速度有影响吗,r,R,我有一个问题,我想运行一个模拟研究,其中模拟取决于两个变量x和yx和y是我想在模拟研究中评估的潜在值向量(如此不同的组合)。此外,对于x和y的每个组合,我需要多个复制(因为其中有一个随机项,x和y的每次运行都会有所不同) 为了举例说明我正在处理的问题,我有以下简化示例: x = 1:10 y = 11:20 iterations = 2000 iter = 1 solution = array(NA,c(length(x),3,iterations)) for(i in x){ fo
x
和y
x
和y
是我想在模拟研究中评估的潜在值向量(如此不同的组合)。此外,对于x
和y
的每个组合,我需要多个复制(因为其中有一个随机项,x
和y
的每次运行都会有所不同)
为了举例说明我正在处理的问题,我有以下简化示例:
x = 1:10
y = 11:20
iterations = 2000
iter = 1
solution = array(NA,c(length(x),3,iterations))
for(i in x){
for(j in y){
for(k in 1:iterations){
z = rnorm(3) + c(i,j,1)
solution[i,,k] = z
}
}
}
然而,在我的实际问题中,在for循环中计算的代码要少得多。但是,我的输入结构与输出结构相同
因此,我想知道的是,使用上面的例子,按照这个顺序设置循环是最有效的还是最好让k in 1:iterations
成为最外层的循环,并尝试在该1循环中使用某种outer()
命令,因为我将评估函数(z
)在网格上x
和y
另外,我对完全不同的设置和设计非常开放。在一天结束时,我希望能够获得一个基于x
和y
并在所有迭代中求平均值的解决方案,即应用(解决方案,c(1,2),平均值)
编辑: 正如向我建议的,下面是我正在使用的实际代码
library(survival)
iter = 2000
n = 120
base = 2
hr = 0.5
m.x = 3
m.y = m.x/hr
ANS = NULL
for (vecX in c(0.3, 0.5, 0.6, 0.7)){
out = NULL
for (vecY in c(0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95)){
m.x.p = m.x/vecX
m.y.p = m.y/vecX
m.x.n = m.x
m.y.n = m.y
n.t = round(n*base/(base+1))
n.c = n - n.t
for (ii in 1:iter){
n.t.p = rbinom(1, n.t, vecY)
n.t.n = n.t - n.t.p
n.c.p = rbinom(1, n.c, vecY)
n.c.n = n.c - n.c.p
S = c(rexp(n.t.p, log(2)/m.y.p), rexp(n.t.n, log(2)/m.y.n), rexp(n.c.p, log(2)/m.x.p), rexp(n.c.n, log(2)/m.x.n))
data1 = data.frame(Group = c(rep("T", n.t), rep("C", n.c)), dx = c(rep("P", n.t.p), rep("N", n.t.n), rep("P", n.c.p), rep("N", n.c.n)), S)
fit = survfit(Surv(data1$S)~data1$Group)
coxfit = coxph(Surv(data1$S)~data1$Group)
HR = exp(coxfit$coefficients)
p.val=summary(coxfit)$logtest["pvalue"]
out = rbind(out, c(vecX, vecY, n.t.p, n.t.n, n.c.p, n.c.n, HR, p.val))
}
}
colnames(out) = c("vecX", "vecY", "n.t.p", "n.t.n", "n.c.p", "n.c.n", "HR", "p.val")
ans = as.data.frame(out)
ANS = rbind(ANS, ans)
}
是的,我相信理论上它应该会有所不同(见下面的例子) R像Fortran一样使用列主顺序(和C不同),所以为了最小化缓存未命中,您可能希望向下遍历列。因此,对于填充矩阵,最佳方法是外循环有我们的列索引的方法 对于n维数组,你也应该记住这一点。在
n=3
的情况下,我想这意味着层是最外层的循环,然后是列,然后是行。不过,我可能是搞错了
我用5000
by5000
矩阵运行了这个快速示例。我们看到了大约50秒的差异,fill_matrix2()
更快
n <- 5000
A <- matrix(NA, n, n)
B <- matrix(NA, n, n)
fill_matrix1 <- function(X, val) {
for (i in 1:nrow(X)) {
for (j in 1:ncol(X)) {
X[i, j] <- val
}
}
return(X)
}
fill_matrix2 <- function(X, val) {
for (j in 1:ncol(X)) {
for (i in 1:nrow(X)) {
X[i, j] <- val
}
}
return(X)
}
system.time(fill_matrix1(A, 0))
system.time(fill_matrix2(B, 0))
n这里循环的顺序实际上是不相关的。如果您分析代码(请参阅帮助(“Rprof”)
),您将看到CPU时间花费在survfit
和coxph
等函数上。当然,在成长中,你应该避免。预先分配到它的最终大小,并填充它,而不是增加它。我想这实际上取决于你在循环中拥有什么,以及你是否可以矢量化它。在您的示例中,您可以通过z@nicola完全删除k
循环。上面的示例完全是虚构的。它更能说明我的结构以及输入和输出。是的,我知道这个例子是虚构的。我的观点是你必须尝试矢量化。根据我的经验,在很多情况下,人们试图通过使用lappy
来节省时间,而不是sapply
或反向循环,在这些情况下,矢量化是可用的,程序员没有意识到这一点。与成功实现矢量化相比,这种优化通常可以忽略不计。所以,如果你真的想优化,试着用一种你可以矢量化的方式重新思考你的代码。如果不能,请不要浪费时间考虑循环顺序。@nicole,在这里发布我的实际代码供人们评论合适吗?我不想因为发布“这是我的代码,请快一点”而被标记@SymbolX我将用我的实际代码更新我的问题。对于较小的“n”,两个函数之间的计时似乎没有太大差异,对于较大的函数,我无法获得一致的行为。也许是因为[当然,我同意我应该预先分配大小。我还可以做些什么来优化代码以更快地运行?正如我指出的:您的第一步应该是分析您的代码。