我注意到julia在矩阵复制时表现出了奇怪的行为。
考虑以下三个函数:
那是一个非常大的差异。这也很令人惊讶。我预计第一个版本会像memcopy一样难以超越,对于一个大的内存块来说,memcopy很难被超越。
第二个版本有指针算术(getindex),分支条件(<=)和每个赋值都有边界检查的开销。然而,每个赋值只需要约3ns时间。
此外,垃圾收集器消耗的时间对于第一个函数来说是不确定的。如果没有进行垃圾收集,则这种显著差异变得微不足道,但它仍然存在。版本3和版本2之间的差距仍然是2.5倍左右的因素。
那么为什么“memcopy”版本没有“赋值”版本高效呢?
考虑以下三个函数:
function priv_memcopyBtoA!(A::Matrix{Int}, B::Matrix{Int}, n::Int)
A[1:n,1:n] = B[1:n,1:n]
return nothing
end
function priv_memcopyBtoA2!(A::Matrix{Int}, B::Matrix{Int}, n::Int)
ii = 1; jj = 1;
while ii <= n
jj = 1 #(*)
while jj <= n
A[jj,ii] = B[jj,ii]
jj += 1
end
ii += 1
end
return nothing
end
function priv_memcopyBtoA3!(A::Matrix{Int}, B::Matrix{Int}, n::Int)
A[1:n,1:n] = view(B, 1:n, 1:n)
return nothing
end
编辑:1)我测试了代码是否会抛出BoundsError
,所以标有jj = 1 #(*)
的那行在最初的代码中缺失。测试结果已经来自于修复后的版本,因此它们保持不变。2)我添加了视图变体,感谢@Colin T Bowers解决了两个问题。
看起来这两个函数应该产生大致相同的代码。然而,我得到的结果是:
A = fill!(Matrix{Int32}(2^12,2^12),2); B = Int32.(eye(2^12));
结果
@timev priv_memcopyBtoA!(A,B, 2000)
0.178327 seconds (10 allocations: 15.259 MiB, 85.52% gc time)
elapsed time (ns): 178326537
gc time (ns): 152511699
bytes allocated: 16000304
pool allocs: 9
malloc() calls: 1
GC pauses: 1
并且
@timev priv_memcopyBtoA2!(A,B, 2000)
0.015760 seconds (4 allocations: 160 bytes)
elapsed time (ns): 15759742
bytes allocated: 160
pool allocs: 4
并且
@timev priv_memcopyBtoA3!(A,B, 2000)
0.043771 seconds (7 allocations: 224 bytes)
elapsed time (ns): 43770978
bytes allocated: 224
pool allocs: 7
那是一个非常大的差异。这也很令人惊讶。我预计第一个版本会像memcopy一样难以超越,对于一个大的内存块来说,memcopy很难被超越。
第二个版本有指针算术(getindex),分支条件(<=)和每个赋值都有边界检查的开销。然而,每个赋值只需要约3ns时间。
此外,垃圾收集器消耗的时间对于第一个函数来说是不确定的。如果没有进行垃圾收集,则这种显著差异变得微不足道,但它仍然存在。版本3和版本2之间的差距仍然是2.5倍左右的因素。
那么为什么“memcopy”版本没有“赋值”版本高效呢?
malloc
都应该有相应的free
。你的答案没有回答我的问题:为什么Julia中的memcopy不如C中的效率高? - BlueLemonwhile
循环在第一次迭代后终止,而在编辑版本中,外部while
循环(正确地)经过 2000 次迭代。 - Colin T Bowers@btime
和Int64
而不是Int32
,对于这三个例程,我分别得到了0.011、0.005、0.006秒。 - Colin T Bowers64位
的机器?如果是这样,我可以重现它。如果我切换到Int64
,我得到0.046、0.014、0.022,大致上是你的结果的4倍。第一个时间差主要来自于malloc/free
,即垃圾回收,对于Int32来说是不稳定的。此外,我怀疑编译器可以将Int64
解释为指针,从而允许其他优化。 - BlueLemon