【发布时间】:2014-11-26 16:57:32
【问题描述】:
考虑以下函数:
function mytest(x, b)
y = zeros(x[:,:,1])
for i in 1:length(b)
y += b[i] * x[:,:,i]
end
return y
end
当我运行它时,我得到以下信息:
x = rand(30,30,100000)
b = rand(100000)
@time mytest(x,b)
elapsed time: 0.571765222 seconds (727837732 bytes allocated, 66.49% gc time)
为什么要分配这么多内存并花费这么多时间进行垃圾回收?代码应该是类型稳定的,我希望+= 运算符不会执行重新分配。但是,似乎每次添加两个矩阵时都会重新分配。
我应该认为这是 Julia 中的一个错误吗?更重要的是,我怎样才能以不重新分配的方式编写这段代码?
编辑:修正了错字。
【问题讨论】:
-
右侧
b[i] * x[:,:,i]首先分配一个临时数组,其中包含乘积的结果,然后将其就地添加到左侧。然后需要对临时数组进行垃圾收集。至少......这就是它与numpy 一起使用的方式。 -
@moarningsun,感谢您的提示。我之前在性能关键代码方面的经验主要是使用 C++ 和 Eigen,它们在获取切片时不会分配临时空间。我已将代码更改为具有三个嵌套的 for 循环,并且分配问题已得到修复。 (在此之前我尝试使用 ArrayViews 包,但这似乎并没有解决问题。)我仍然很好奇是否有更好的方法。
-
@JimGarrison:查看讨论here。
+=只是语法糖(至少现在是这样),所以我认为它总是重新分配(但如果我错了,请有人纠正我)。另外,我很想看看三个循环如何解决您的问题。 -
看起来这可能在 Julia 0.4 中得到修复:github.com/JuliaLang/julia/pull/9150
标签: memory-management garbage-collection profiling julia