У меня есть код для оптимизации с некоторыми критическими частями, для которых я не хочу, чтобы gc запускал выделение памяти.
Точнее, у меня есть тип действительного числа
struct AFloat{T<:AbstractFloat} <: Real
value::T
j::Int
end
Я должен отслеживать, чтобы выполнить автоматическое дифференцирование.Таким образом, для любой арифметической операции мне нужно сделать несколько записей в ленте.Производительность здесь очень важна (она имеет реальное значение, если у вас есть еще один ассигнт на арифметическую операцию!)У меня есть выбор между AFloat{T}
или просто использовать примитивный тип для отслеживания индекса j:
primitive type AFloat64 <: Real sizeof(Int) end
Однако меня смущают эти результаты:
Первая часть: ok
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)
-> Я бы пришел к выводу, что нажатие примитивного типа позволяет избежать одного выделения памяти по сравнению с 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 распределений против 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?Почему?
Если быть синтетическим , в Джулии, есть ли разница в распределении памяти и памяти между foo_A и foo_Primitive , где:
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)