Memory Julia嵌套循环占用了大量内存
我有一个嵌套循环迭代方案,它占用了大量内存。我知道我不应该有全局变量,但即使在我将所有内容都包含在一个函数中,记忆情况也没有改善。它只是在每次迭代后累积,就好像没有垃圾回收一样 下面是一个与我的代码类似的可行示例 我有两个文件。首先,Memory Julia嵌套循环占用了大量内存,memory,memory-management,julia,Memory,Memory Management,Julia,我有一个嵌套循环迭代方案,它占用了大量内存。我知道我不应该有全局变量,但即使在我将所有内容都包含在一个函数中,记忆情况也没有改善。它只是在每次迭代后累积,就好像没有垃圾回收一样 下面是一个与我的代码类似的可行示例 我有两个文件。首先,函数.jl: ##functions.jl module functions function getMatrix(A) L = rand(A,A); return L; end function loopOne(A, B) res =
函数.jl
:
##functions.jl
module functions
function getMatrix(A)
L = rand(A,A);
return L;
end
function loopOne(A, B)
res = 0;
for i = 1:B
res = inv(getMatrix(A));
end
return(res);
end
end
##main.jl
include("functions.jl")
function main(C)
res = 0;
A = 50;
B = 30;
for i =1:C
mat = functions.loopOne(A,B);
res = mat .+ 1;
end
return res;
end
main(100)
第二个文件main.jl
:
##functions.jl
module functions
function getMatrix(A)
L = rand(A,A);
return L;
end
function loopOne(A, B)
res = 0;
for i = 1:B
res = inv(getMatrix(A));
end
return(res);
end
end
##main.jl
include("functions.jl")
function main(C)
res = 0;
A = 50;
B = 30;
for i =1:C
mat = functions.loopOne(A,B);
res = mat .+ 1;
end
return res;
end
main(100)
当我执行julia main.jl
时,内存会随着我在main(C)
中扩展C
而增加(当我将C
增加到1000000时,有时会增加到数百万个分配和10GB以上)
我知道这个例子看起来毫无用处,但它与我的结构相似。有人能帮忙吗?多谢各位
更新:
Michael K.Borregaard给出了一个非常有用的答案:
module Functions #1
function loopOne!(res, mymatrix, B) #2
for i = 1:B
res .= inv(rand!(mymatrix)) #3
end
return res #4
end
end
function some_descriptive_name(C) #5
A, B = 50, 30 #6
res, mymat = zeros(A,A), zeros(A,A)
for i =1:C
res .= Functions.loopOne!(res, mymat, B) .+ 1
end
return res
但是,当我计时时,分配和内存仍然会随着我拨号C
而增加
@time some_descriptive_name(30)
0.057177 seconds (11.77 k allocations: 58.278 MiB, 9.58% gc time)
@time some_descriptive_name(60)
0.113808 seconds (23.53 k allocations: 116.518 MiB, 9.63% gc time)
我认为问题来自inv
功能。如果我将代码更改为:
function some_descriptive_name(C) #5
A, B = 50, 30 #6
res, mymat = zeros(A,A), zeros(A,A)
for i =1:C
res .= res .+ 1
end
return res
end
内存和分配将保持不变:
@time some_descriptive_name(3)
0.000007 seconds (8 allocations: 39.438 KiB)
@time some_descriptive_name(60)
0.000037 seconds (8 allocations: 39.438 KiB)
使用
inv
后是否有办法“清除”内存?由于我没有创建任何新内容或存储任何新内容,因此内存使用量应该保持不变。至少有几个指针:
rand
使用随机值填充现有数组res=0
行将res
定义为Int
,但随后将矩阵{Float}
分配给它(结果是inv(getMatrix)
)。更改代码中变量的类型会使编译器很难确定变量的类型,这会导致代码速度变慢函数的模块,但您没有编写它
res=inv
代码行不断覆盖该值,因此循环不执行任何操作module Functions #1
function loopOne!(res, mymatrix, B) #2
for i = 1:B
res .= inv(rand!(mymatrix)) #3
end
return res #4
end
end
function some_descriptive_name(C) #5
A, B = 50, 30 #6
res, mymat = zeros(A,A), zeros(A,A)
for i =1:C
res .= Functions.loopOne!(res, mymat, B) .+ 1
end
return res
end
评论:
结尾
表示他们将修改参数(比如通过引用传递变量而不使其在C++中为常量)=
操作符指示您不是在创建新容器,而是在覆盖现有容器的元素。rand代码>函数覆盖mymatrix
main
约定,因为大多数代码都是由用户调用的,而不是通过执行程序调用的inv
函数上
对更新的答复:
inv功能没有什么问题,只是操作成本很高。但我想你可能误解了记忆体计数的作用。并不是内存使用量增加了,就像你在C++中寻找的那样,如果你有一个指向一个从未被释放的对象的指针(内存泄漏)。内存使用是恒定的,但分配的总和会增加,因为inv
函数必须进行一些内部分配
以这个例子为例
for i in 1:n
b = [1, 2, 3, 4] # Here a length-4 Array{Int64} is initialized in memory, cost is 32 bytes
end # Here, that memory is released.
对于For循环的每次运行,分配32个字节,释放32个字节。当循环结束时,无论n,都将从此操作中分配0个字节。但是Julia的内存跟踪只添加了分配,所以在运行代码之后,您将看到32*n字节的分配。
julia这样做的原因是在RAM中分配空间是计算中最昂贵的操作之一,因此减少分配是加速代码的一个好方法。但你无法避免
因此,您的代码(采用新格式)没有任何问题—您看到的内存分配和占用的时间只是执行大型(昂贵)操作的结果 您的代码在我的julia笔记本435ms和252MiB(julia 0.6)中稍作修改(对外部文件的引用)后就完成了,您的安装还存在其他问题顺便说一句,您不需要在中使用分号julia@stefanbachert当增加循环数时,它是否会改变?另外,当我尝试在不执行inv的情况下使用相同的函数时,我的代码要快得多。inv有什么特别不对劲的地方吗?有趣的是,看到Julia像C++一样编写,这也是交叉发布到的;这里也有一些讨论。即使我将
rand(A,A)
更改为[1 2;3 4]
,我仍然看到同样的情况,即即使不使用rand(A,A)
,内存消耗也会增加。4.我知道这没什么用。这只是一个可行的例子。既然我没有创建任何新的东西,内存消耗难道不应该保持不变吗?所以我应该在循环外创建一个虚拟变量,并允许循环内的操作“填充”虚拟变量?对不起!在我读到你的评论之前,我发布了这篇文章。当我完成后,我会给你一个投票。在我看来,这是一个非常清楚的答案,即使没有评论。你这么认为?那我就改变那一点建议。