gpt4 book ai didi

julia - 为什么数组+=(没有@.)会产生如此多的内存分配?

转载 作者:行者123 更新时间:2023-12-04 23:13:59 28 4
gpt4 key购买 nike

我不明白为什么数组的 += 操作会产生如此多的内存分配,但是在应用 @ 时它会得到修复。

function loop()
a = randn(10)
total = similar(a)

for i=1:1000
total += a
end
end

function loopdot()
a = randn(10)
total = similar(a)

for i=1:1000
@. total += a
end
end


loop()
loopdot()

Profile.clear_malloc_data()

loop()
loopdot()

产生
160000         total += a


0         @. total += a

最佳答案

total += atotal = a + total 相同这是一个矢量化操作,如:

out = similar(a)
for i in eachindex(a)
out[i] = total[i] + a[i]
end
total = out

因为在内部是
total = +(total,a)

这就像 MATLAB、Python 或 R 一样,因此有一个为向量化操作分配的临时数组,然后是 =设置 total 的引用到这个新数组。这就是为什么矢量化操作比传统的低级循环慢的原因,也是使用像 NumPy 这样的东西可以比 Python 更快但不能完全达到 C(因为这些临时性!)的主要原因之一。
@. total += atotal .= total .+ a 相同. This blog post解释说在 Julia 中有通过匿名函数进行语义点融合,因此对应于执行以下操作:
# Build an anonymous function for the fused operation
f! = (a,b,c) -> (a[i] = b[i] + c[i])
# Now loop it, since it's `.=` don't make a temporary
for i in eachindex(a)
f!(total,total,a)
end

其中更新 total就地而不创建临时数组。

Julia 中的融合在语义上发生:将点操作转换为匿名函数加上 broadcast! call(本质上是我在那里写的循环)在解析时完成,并且匿名函数被编译,因此这是有效的。这对于其他原因也非常有用。通过重载 broadcast!通用 f! ,这就是 GPUArrays.jl 之类的事情自动构建高效的单个内核,在 GPU 上进行就地更新。这与 MATLAB、Python 和 R 不同,其中不同的向量化函数被视为不同的函数调用,因此必须计算返回值,因此是临时数组。

关于julia - 为什么数组+=(没有@.)会产生如此多的内存分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48036171/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com