我运行julia --track-allocation prof.jl
导致以下输出:
- using FixedSizeArrays
-
- immutable KernelVals{T}
- wavenumber::T
- vect::Vec{3,T}
- dist::T
- green::Complex{T}
- gradgreen::Vec{3,Complex{T}}
- end
-
- function kernelvals(k, x, y)
- r = x - y
0 R2 = r[1]*r[1]
0 R2 += r[2]*r[2]
0 R2 += r[3]*r[3]
0 R = sqrt(R2)
-
0 γ = im*k
0 expn = exp(-γ * R)
0 fctr = 1.0 / (4.0*pi*R)
0 green = fctr * expn
64 gradgreen = -(γ + 1/R) * green / R * r
-
0 KernelVals(k, r, R, green, gradgreen)
- end
-
- function payload()
- x = Vec{3,Float64}(0.47046262275611883,0.8745228524771103,-0.049820876498487966)
0 y = Vec{3,Float64}(-0.08977259509004082,0.543199687600189,0.8291184043296924)
0 k = 1.0
0 kv = kernelvals(k,x,y)
- return kv
- end
-
- function driver()
- println("Flush result: ", payload())
0 Profile.clear_malloc_data()
0 payload()
- end
-
- driver()
我无法摆脱从gradgreen...
开始的行的最终内存分配。我跑了@code_warntype kernelsvals(...)
,没有发现任何类型的不稳定或不确定性。
julia-0.4.6
和julia-0.5.0-pre
上的分配模式相同。
这个函数将是我正在实现的边界元素方法的内核。它将被称为数百万次,导致总内存分配可以增长到可用物理内存的倍数 对我来说。
我使用FixedSizeArrays
的原因是为了避免与创建小Array
s相关的分配。
报告分配的准确位置取决于对代码的非常敏感的方式。在某些时候,内存分析器将1/(4*pi*R)
归咎于行触发分配。
高度赞赏任何有关如何编写代码以获得可预测分配模式的帮助或一般提示。
答案 0 :(得分:3)
经过一些实验,我终于设法摆脱了所有的分配。罪魁祸首证明是FixedSizeArrays
中扩展的推广架构。显然,将复杂标量与实数向量相乘可以在此过程中产生一个临时值。
用
替换gradgreen
的定义
c = -(γ + 1/R) * green / R
gradgreen = Vec(c*r[1], c*r[2], c*r[3])
导致无分配运行。在我的基准测试示例中,执行时间从6.5秒降至4.15秒。总分配大小从4.5 GB到1.4 GB。
EDT :向FixedSizeArrays
开发人员报告此问题,他们立即修复了(谢谢!)。分配完全消失了。