为何Julia中sum调用lambda的迭代次数增加时分配内存随之增长?
问题解答
你看到的内存分配随迭代次数增长,核心原因是生成器表达式h() for _ in 1:N的迭代机制带来了每次迭代的少量堆分配,和闭包本身的内存占用没关系——你的闭包确实只需要常量内存来存储捕获的Ref{Int}(Julia自动把要修改的外部变量包装成了Ref)和闭包结构。
具体拆解:
- 当你写
() -> i += 1这种修改外部变量的闭包时,Julia会自动把i包装成Ref{Int}类型,这样闭包才能修改外层函数的变量。这个Ref本身是固定大小的,不会随迭代次数增长。 - 但你用
sum(h() for _ in 1:N)时,这个生成器的迭代器Base.Generator在每次调用iterate时,会触发闭包调用,同时会产生少量临时分配(比如用于维护迭代状态的小结构体)。这些分配每次迭代都有,累计起来就会随迭代次数线性增长——你看1e6次对应3M分配,1e7次对应30M分配,刚好是10倍关系,也验证了这一点。 - 如果换用手动循环累加,就不会有这些额外分配:
运行这段代码你会发现内存分配几乎为0,因为直接操作变量跳过了生成器的额外开销。h = f() s = 0 @time for _ in 1:1000000 s += h() end println(s)
另外补充:你看到的分配都是很小的临时对象,Julia的GC会自动回收,但累计起来就会显示出随N增长的内存占用量。
内容的提问来源于stack exchange,提问作者Matteo
相关产品推荐
相关产品推荐

