Julia:使用 base.ntuples 函数的类型稳定性
Julia: type stability using the base.ntuples function
我最近开始使用 Julia,目前正在为打字的某些方面而苦苦挣扎。我正在尝试定义一个类型 TensorTrain (https://www.researchgate.net/profile/Ivan_Oseledets2/publication/220412263_Tensor-Train_Decomposition/links/5bbfb5c5299bf1004c5a56e3/Tensor-Train-Decomposition.pdf),但我无法获得我定义为稳定的方法之一:
abstract type AbstractTensorTrain <: Any end
struct TensorTrain{T<:AbstractFloat} <: AbstractTensorTrain
cores::Vector{Array{T,3}}
end
Base.size(t::TensorTrain, d::Int) = size(t.cores[d],2)
Base.size(t::TensorTrain) = ntuple(d->size(t,d),length(t.cores))
但是如果我运行:
@code_warntype TensorTrain([rand(2,3,4)]);
我得到:
Variables
#self#::Core.Compiler.Const(size, false)
t::TensorTrain{Float64}
#19::var"#19#20"{TensorTrain{Float64}}
d::Int64
Body::Tuple{Vararg{Int64,N} where N}
1 ─ %1 = Base.getproperty(t, :cores)::Array{Array{Float64,3},1}
│ (d = Main.length(%1))
│ %3 = Main.:(var"#19#20")::Core.Compiler.Const(var"#19#20", false)
│ %4 = Core.typeof(t)::Core.Compiler.Const(TensorTrain{Float64}, false)
│ %5 = Core.apply_type(%3, %4)::Core.Compiler.Const(var"#19#20"{TensorTrain{Float64}}, false)
│ (#19 = %new(%5, t))
│ %7 = #19::var"#19#20"{TensorTrain{Float64}}
│ %8 = Main.ntuple(%7, d)::Tuple{Vararg{Int64,N} where N}
└── return %8
这是为什么?
因为 d = length(t.cores)
仅在运行时已知,所以 ntuple
无法静态推断 N
参数。有一种方法采用 Val
,这在其他情况下对类型稳定性很有用,但它在这里没有改变任何东西——d
仍然是动态的。
您可以将 cores
设为 NTuple
或 StaticVector
,但(它们实际上是相同的东西),这样就可以了。但是在深入研究类型级编程之前,一定要检查它是否真的有所作为。
我最近开始使用 Julia,目前正在为打字的某些方面而苦苦挣扎。我正在尝试定义一个类型 TensorTrain (https://www.researchgate.net/profile/Ivan_Oseledets2/publication/220412263_Tensor-Train_Decomposition/links/5bbfb5c5299bf1004c5a56e3/Tensor-Train-Decomposition.pdf),但我无法获得我定义为稳定的方法之一:
abstract type AbstractTensorTrain <: Any end
struct TensorTrain{T<:AbstractFloat} <: AbstractTensorTrain
cores::Vector{Array{T,3}}
end
Base.size(t::TensorTrain, d::Int) = size(t.cores[d],2)
Base.size(t::TensorTrain) = ntuple(d->size(t,d),length(t.cores))
但是如果我运行:
@code_warntype TensorTrain([rand(2,3,4)]);
我得到:
Variables
#self#::Core.Compiler.Const(size, false)
t::TensorTrain{Float64}
#19::var"#19#20"{TensorTrain{Float64}}
d::Int64
Body::Tuple{Vararg{Int64,N} where N}
1 ─ %1 = Base.getproperty(t, :cores)::Array{Array{Float64,3},1}
│ (d = Main.length(%1))
│ %3 = Main.:(var"#19#20")::Core.Compiler.Const(var"#19#20", false)
│ %4 = Core.typeof(t)::Core.Compiler.Const(TensorTrain{Float64}, false)
│ %5 = Core.apply_type(%3, %4)::Core.Compiler.Const(var"#19#20"{TensorTrain{Float64}}, false)
│ (#19 = %new(%5, t))
│ %7 = #19::var"#19#20"{TensorTrain{Float64}}
│ %8 = Main.ntuple(%7, d)::Tuple{Vararg{Int64,N} where N}
└── return %8
这是为什么?
因为 d = length(t.cores)
仅在运行时已知,所以 ntuple
无法静态推断 N
参数。有一种方法采用 Val
,这在其他情况下对类型稳定性很有用,但它在这里没有改变任何东西——d
仍然是动态的。
您可以将 cores
设为 NTuple
或 StaticVector
,但(它们实际上是相同的东西),这样就可以了。但是在深入研究类型级编程之前,一定要检查它是否真的有所作为。