我有一些代码可以针对某些关键部分进行优化,我不希望gc触发内存分配。
更确切地说,我有一个实数类型
struct AFloat{T<:AbstractFloat} <: Real
value::T
j::Int
end
我必须跟踪以执行自动区分。因此,对于任何算术运算,我必须在磁带中进行一些注册。性能在这里非常重要(如果你对每个算术运算有一个更多的分配,它会产生真正的不同!)。我可以选择AFloat{T}
或简单地使用基本类型来跟踪索引j:
primitive type AFloat64 <: Real sizeof(Int) end
但是,我对这些结果感到困惑:
第一部分:好的
using BenchmarkTools
struct A n::Int64 end
vA=A[A(1)];
@time push!(vA,A(2))
v=Int64[1];
@time push!(v,2)
返回
0.000011 seconds (6 allocations: 224 bytes)
0.000006 seconds (5 allocations: 208 bytes)
与以下内容相符:
@btime push!(vA,A(2))
@btime push!(v,2)
返回
46.410 ns (1 allocation: 16 bytes)
37.890 ns (0 allocations: 0 bytes)
- &GT;我会得出结论,与 struct 相比,推动原语类型避免一个内存分配(是不是?)
第二部分:......有问题......?
我感到困惑,我无法解释这些结果:
foo_A() = A(1);
foo_F64() = Float64(1.);
foo_I64() = Int64(1);
@time foo_A()
@time foo_F64()
@time foo_I64()
返回
0.000004 seconds (5 allocations: 176 bytes)
0.000005 seconds (5 allocations: 176 bytes)
0.000005 seconds (4 allocations: 160 bytes)
Q1如何解释差异foo_F64()与foo_I64()(5分配vs 4分配)?
此外,结果似乎与@btime输出不一致:
@btime foo_A()
3.179 ns (0 allocations: 0 bytes)
@btime foo_F64()
3.801 ns (0 allocations: 0 bytes)
@btime foo_I64()
3.180 ns (0 allocations: 0 bytes)
Q2:@time或@btime的答案是什么?为什么?
合成,在Julia中, foo_A 和 foo_Primitive 之间的性能和内存分配存在差异,其中:< / p>
struct A n::Int64 end
foo_A() = A(1)
foo_Primitive() = Int64(1)
我知道使用@time或@btime时,使用如此小的表达式会产生副作用的风险。理想情况下,最好有一些朱莉娅的内部知识来回答。但我不
julia> versioninfo()
Julia Version 0.6.2
Commit d386e40c17 (2017-12-13 18:08 UTC)
Platform Info:
OS: Linux (x86_64-pc-linux-gnu)
CPU: Intel(R) Xeon(R) CPU E5-2603 v3 @ 1.60GHz
WORD_SIZE: 64
BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
LAPACK: libopenblas64_
LIBM: libopenlibm
LLVM: libLLVM-3.9.1 (ORCJIT, haswell)
答案 0 :(得分:1)
您所看到的分配只是来自REPL afaict的时间副作用 如果你把它们放在一个函数中,那么你使用结构或基本类型的分配是相同的:
julia> function f()
vA=[A(1)]
@time push!(vA,A(2))
v=[1]
@time push!(v,2)
end
f (generic function with 1 method)
julia> f();
0.000000 seconds (1 allocation: 32 bytes)
0.000000 seconds (1 allocation: 32 bytes)