Julia循环和R循环一样慢
Julia和R中的下面代码表明总体方差的估计量是一个有偏估计量,即它取决于样本量,无论我们对不同观测值平均多少次,对于少量数据点,它不等于总体方差 Julia大约需要10秒才能完成两个循环,R大约需要7秒。 如果我将代码保留在循环中,则R和Julia中的循环将占用相同的时间,如果我仅通过Julia循环和R循环一样慢,r,performance,loops,julia,R,Performance,Loops,Julia,Julia和R中的下面代码表明总体方差的估计量是一个有偏估计量,即它取决于样本量,无论我们对不同观测值平均多少次,对于少量数据点,它不等于总体方差 Julia大约需要10秒才能完成两个循环,R大约需要7秒。 如果我将代码保留在循环中,则R和Julia中的循环将占用相同的时间,如果我仅通过s=s+I+j对迭代器求和Julia在~0.15s内完成,而R在~0.5s内完成 是Julia循环变慢了还是R变快了? 如何为Julia提高下面代码的速度? R代码能变得更快吗 朱莉娅: using Plots
s=s+I+j对迭代器求和
Julia在~0.15s内完成,而R在~0.5s内完成
是Julia循环变慢了还是R变快了?
如何为Julia提高下面代码的速度?
R代码能变得更快吗
朱莉娅:
using Plots
trials = 100000
sample_size = 10;
sd = Array{Float64}(trials,sample_size-1)
tic()
for i = 2:sample_size
for j = 1:trials
res = randn(i)
sd[j,i-1] = (1/(i))*(sum(res.^2))-(1/((i)*i))*(sum(res)*sum(res))
end
end
toc()
sd2 = mean(sd,1)
plot(sd2[1:end])
trials = 100000
sample_size = 10
sd = matrix(, nrow = trials, ncol = sample_size-1)
start_time = Sys.time()
for(i in 2:sample_size){
for(j in 1:trials){
res <- rnorm(n = i, mean = 0, sd = 1)
sd[j,i-1] = (1/(i))*(sum(res*res))-(1/((i)*i))*(sum(res)*sum(res))
}
}
end_time = Sys.time()
end_time - start_time
sd2 = apply(sd,2,mean)
plot(sqrt(sd2))
R:
using Plots
trials = 100000
sample_size = 10;
sd = Array{Float64}(trials,sample_size-1)
tic()
for i = 2:sample_size
for j = 1:trials
res = randn(i)
sd[j,i-1] = (1/(i))*(sum(res.^2))-(1/((i)*i))*(sum(res)*sum(res))
end
end
toc()
sd2 = mean(sd,1)
plot(sd2[1:end])
trials = 100000
sample_size = 10
sd = matrix(, nrow = trials, ncol = sample_size-1)
start_time = Sys.time()
for(i in 2:sample_size){
for(j in 1:trials){
res <- rnorm(n = i, mean = 0, sd = 1)
sd[j,i-1] = (1/(i))*(sum(res*res))-(1/((i)*i))*(sum(res)*sum(res))
}
}
end_time = Sys.time()
end_time - start_time
sd2 = apply(sd,2,mean)
plot(sqrt(sd2))
一般来说,在Julia中使用全局变量的速度很慢,应该可以让您的速度与R相当。您应该将代码封装在函数中,以使其速度更快 以下是我笔记本电脑上的计时信息(我只删掉了相关部分): 另外,如果您使用
randn
而不是randn
您可以进一步加速,因为您可以避免重新分配res
向量(我不会对代码进行其他优化,因为与R相比,这种优化对Julia是不同的;此代码中所有其他可能的加速将以类似的方式帮助Julia和R):
最后,最好使用BenchmarkTools
package来度量Julia中的执行时间。首先将从Julia 0.7中删除tic
和toc
函数。第二,如果使用编译和执行时间,则可以混合使用(当运行两次test
函数时,您会发现第二次运行时时间减少了,因为Julia没有花时间编译函数)
编辑:
您可以将试验
、样本大小
和sd
保留为全局变量,但应在它们前面加上const
。那么,在函数中封装一个循环就足够了,如下所示:
const trials = 100000;
const sample_size = 10;
const sd = Array{Float64}(trials,sample_size-1);
function f()
for i = 2:sample_size
for j = 1:trials
res = randn(i)
sd[j,i-1] = (1/(i))*(sum(res.^2))-(1/((i)*i))*(sum(res)*sum(res))
end
end
end
tic()
f()
toc()
现在,对于并行的@parallel
:
首先,您应该在@parallel
之前使用@sync
,以确保所有工作正常进行(即,在转到下一条指令之前,所有工作人员都已完成)。要了解为什么需要这样做,请在具有多个辅助进程的系统上运行以下代码:
sd = SharedArray{Float64}(10^6);
@parallel for i = 1:2
if i < 2
sd[i] = 1
else
for j in 2:10^6
sd[j] = 1
end
end
end
minimum(sd) # most probably prints 0.0
sleep(1)
minimum(sd) # most probably prints 1.0
一般来说,在Julia中使用全局变量的速度很慢,应该可以让您的速度与R相当。您应该将代码封装在函数中,以使其速度更快 以下是我笔记本电脑上的计时信息(我只删掉了相关部分): 另外,如果您使用
randn
而不是randn
您可以进一步加速,因为您可以避免重新分配res
向量(我不会对代码进行其他优化,因为与R相比,这种优化对Julia是不同的;此代码中所有其他可能的加速将以类似的方式帮助Julia和R):
最后,最好使用BenchmarkTools
package来度量Julia中的执行时间。首先将从Julia 0.7中删除tic
和toc
函数。第二,如果使用编译和执行时间,则可以混合使用(当运行两次test
函数时,您会发现第二次运行时时间减少了,因为Julia没有花时间编译函数)
编辑:
您可以将试验
、样本大小
和sd
保留为全局变量,但应在它们前面加上const
。那么,在函数中封装一个循环就足够了,如下所示:
const trials = 100000;
const sample_size = 10;
const sd = Array{Float64}(trials,sample_size-1);
function f()
for i = 2:sample_size
for j = 1:trials
res = randn(i)
sd[j,i-1] = (1/(i))*(sum(res.^2))-(1/((i)*i))*(sum(res)*sum(res))
end
end
end
tic()
f()
toc()
现在,对于并行的@parallel
:
首先,您应该在@parallel
之前使用@sync
,以确保所有工作正常进行(即,在转到下一条指令之前,所有工作人员都已完成)。要了解为什么需要这样做,请在具有多个辅助进程的系统上运行以下代码:
sd = SharedArray{Float64}(10^6);
@parallel for i = 1:2
if i < 2
sd[i] = 1
else
for j in 2:10^6
sd[j] = 1
end
end
end
minimum(sd) # most probably prints 0.0
sleep(1)
minimum(sd) # most probably prints 1.0
在
R
中,我会这样做:my.sd在你把它包装成一个函数后,你会看到几乎所有的时间都花在randn
中,它与Julia vs R中循环的速度无关。你也在写sum(res)*sum(res
而不是sum(res)^2
,和sum(res.^2)
而不是sum(abs2,res)
,两者都在浪费资源。您可以重写为:sd[j,i-1]=sum(abs2,res)/i-(sum(res)/i)^2
@DNF,所有这些都是正确的,但是在Julia中,在全局范围内执行时,循环本身也比在函数中执行的循环慢。在R
中,我会这样做:my.sd,在将其包装到函数中之后,你会发现几乎所有的时间都花在randn
,这与Julia vs R中循环的速度无关。你也在写sum(res)*sum(res)
而不是sum(res)^2
,和sum(res)
而不是sum(abs2,res)
,这都是在浪费资源。您可以重写为:sd[j,i-1]=sum(abs2,res)/i-(sum(res)/i)^2
@DNF,所有这些都是正确的,但是在Julia中,在全局范围内执行时,循环本身也比在函数中执行的循环慢。谢谢您的回答。当我使用共享数组进行并行计算时,代码也变得很快(0.1s)。除了我使用六个核之外,这和全局变量有什么关系吗?是否可以用更好的方式定义全局变量而不是将代码放在函数中?是否有任何参考资料解释为什么全局变量使Julia更快?使用全局变量是否存在任何风险?Julia手册对此进行了解释。对于SharedArray
本身在这里没有帮助@parallel
帮助。我将改进我的答案以涵盖这一点。答案的开头听起来像是全局变量使Julia更快,而事实恰恰相反。也许可以澄清一下。另外,如果你移动randn
julia> @macroexpand @sync @parallel for i = 2:sample_size
for j = 1:trials
res = randn(i)
sd[j,i-1] = (1/(i))*(sum(res.^2))-(1/((i)*i))*(sum(res)*sum(res))
end
end
quote # task.jl, line 301:
(Base.sync_begin)() # task.jl, line 302:
#19#v = (Base.Distributed.pfor)(begin # distributed\macros.jl, line 172:
function (#20#R, #21#lo::Base.Distributed.Int, #22#hi::Base.Distributed.Int) # distributed\macros.jl, line 173:
for i = #20#R[#21#lo:#22#hi] # distributed\macros.jl, line 174:
begin # REPL[22], line 2:
for j = 1:trials # REPL[22], line 3:
res = randn(i) # REPL[22], line 4:
sd[j, i - 1] = (1 / i) * sum(res .^ 2) - (1 / (i * i)) * (sum(res) * sum(res))
end
end
end
end
end, 2:sample_size) # task.jl, line 303:
(Base.sync_end)() # task.jl, line 304:
#19#v
end