Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Julia循环和R循环一样慢_R_Performance_Loops_Julia - Fatal编程技术网

Julia循环和R循环一样慢

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

Julia和R中的下面代码表明总体方差的估计量是一个有偏估计量,即它取决于样本量,无论我们对不同观测值平均多少次,对于少量数据点,它不等于总体方差

Julia大约需要10秒才能完成两个循环,R大约需要7秒。 如果我将代码保留在循环中,则R和Julia中的循环将占用相同的时间,如果我仅通过
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更快,而事实恰恰相反。也许可以澄清一下。另外,如果你移动
randnjulia> @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