如何在 Julia 中表示高性能的异构堆栈
How to represent a performant heterogenous stack in Julia
我想在 Julia 中实现一种简单的串联语言(也称为 Joy 或 Factor)作为 DSL,但我对如何以最佳方式表示堆栈感到困惑。
代表数据和程序代码的堆栈应该能够容纳一系列不同类型的项目。在最简单的情况下,Ints、Symbols 和再次递归地堆栈(以表示引用的代码)。然后该程序将大量使用 push!流行!在不同的此类堆栈之间洗牌。
Julia 中一个明显的实现是使用元胞数组,该实现有效但运行速度相当慢。例如,以下 Joy 堆栈 [ 1 [ 1 2 +] i + ]
(计算结果为 [4]
)可以在 Julia 中实现为
stack = Any[:+,:i,Any[:+,2,1],1]
。我的典型代码如下所示:
x = pop!(callstack)
if isa(x,Int)
push!(x,datastack)
elseif isa(x,Symbol)
do_stuff(x,datastack)
end
然而,这运行起来真的很慢并且使用了大量的内存分配,可能是因为这样的代码不是类型稳定的(这是 Julia 中的一个很大的性能瓶颈)。
使用 C,我会将堆栈紧凑地表示为一个并集的数组(或者作为一个链表):
typedef union Stackelem{
int val;
char *sym;
union Stackelem *quote;
} Stackelem;
Stackelem stack[n];
但是如何在 Julia 中实现异构堆栈的这种紧凑表示,以及如何避免类型不稳定?
这是一种方式,另一种方式是用 Vector{Any} 类型表示 args:
julia> immutable Exp
head::Symbol
args::Tuple
end
julia> q = Exp(:+, (1, Exp(:-, (3, 4))))
Exp(:+,(1,Exp(:-,(3,4))))
编辑:另一种表示方式可能是:
immutable QuoteExp{T} ; vec::Vector{T} ; end
typealias ExpTyp Union{QuoteExp, Int, Symbol}
typealias Exp QuoteExp{ExpTyp}
然后您可以执行以下操作:
julia> x = Exp(ExpTyp[:+, 1, 2])
QuoteExp{Union{Int64,QuoteExp{T},Symbol}}(Union{Int64,QuoteExp{T},Symbol}[:+,1,2])
julia> x.vec[1]
:+
julia> x.vec[2]
1
julia> x.vec[3]
2
julia> push!(x.vec,:Scott)
4-element Array{Union{Int64,QuoteExp{T},Symbol},1}:
:+
1
2
:Scott
julia> x.vec[4]
:Scott
我想在 Julia 中实现一种简单的串联语言(也称为 Joy 或 Factor)作为 DSL,但我对如何以最佳方式表示堆栈感到困惑。
代表数据和程序代码的堆栈应该能够容纳一系列不同类型的项目。在最简单的情况下,Ints、Symbols 和再次递归地堆栈(以表示引用的代码)。然后该程序将大量使用 push!流行!在不同的此类堆栈之间洗牌。
Julia 中一个明显的实现是使用元胞数组,该实现有效但运行速度相当慢。例如,以下 Joy 堆栈 [ 1 [ 1 2 +] i + ]
(计算结果为 [4]
)可以在 Julia 中实现为
stack = Any[:+,:i,Any[:+,2,1],1]
。我的典型代码如下所示:
x = pop!(callstack)
if isa(x,Int)
push!(x,datastack)
elseif isa(x,Symbol)
do_stuff(x,datastack)
end
然而,这运行起来真的很慢并且使用了大量的内存分配,可能是因为这样的代码不是类型稳定的(这是 Julia 中的一个很大的性能瓶颈)。
使用 C,我会将堆栈紧凑地表示为一个并集的数组(或者作为一个链表):
typedef union Stackelem{
int val;
char *sym;
union Stackelem *quote;
} Stackelem;
Stackelem stack[n];
但是如何在 Julia 中实现异构堆栈的这种紧凑表示,以及如何避免类型不稳定?
这是一种方式,另一种方式是用 Vector{Any} 类型表示 args:
julia> immutable Exp
head::Symbol
args::Tuple
end
julia> q = Exp(:+, (1, Exp(:-, (3, 4))))
Exp(:+,(1,Exp(:-,(3,4))))
编辑:另一种表示方式可能是:
immutable QuoteExp{T} ; vec::Vector{T} ; end
typealias ExpTyp Union{QuoteExp, Int, Symbol}
typealias Exp QuoteExp{ExpTyp}
然后您可以执行以下操作:
julia> x = Exp(ExpTyp[:+, 1, 2])
QuoteExp{Union{Int64,QuoteExp{T},Symbol}}(Union{Int64,QuoteExp{T},Symbol}[:+,1,2])
julia> x.vec[1]
:+
julia> x.vec[2]
1
julia> x.vec[3]
2
julia> push!(x.vec,:Scott)
4-element Array{Union{Int64,QuoteExp{T},Symbol},1}:
:+
1
2
:Scott
julia> x.vec[4]
:Scott