Hi all,
I am implementing genetic proggraming (GP) in julia. In GP, I need to evaluate mathematical expressions represented by tree structures.
This is extracted and simplified code relating to the evaluation.
struct FuncNode{S, T, U}
func::S
args::Tuple{T, U}
end
struct ConstNode{T <: Real}
value::T
end
function evaluate(node::FuncNode)
arg1 = evaluate(node.args[1])
arg2 = evaluate(node.args[2])
return node.func(arg1, arg2)
end
add_trees(tree1, tree2) = FuncNode(+, (tree1, tree2))
evaluate(node::ConstNode) = node.value
tree1 = FuncNode(+,
(FuncNode(+,
(ConstNode(1),
ConstNode(2))),
FuncNode(-,
(ConstNode(3),
ConstNode(4)))))
tree2 = FuncNode(/, (ConstNode(1), ConstNode(1)))
@show evaluate(tree1)
@show evaluate(add_trees(tree1, tree2))
In an original code, there is a function to create trees and thousands of trees are generated randomly and then evaluated. When I run the original code with --trace-compile=stderr
, it seems many precompilation occur when creating and evaluating trees like this:
( I picked up some messages, because there are too many messages......)
precompile(Tuple{Type{JuliaGSGP.FuncNode{T, S, U} where U where S where T}, JuliaGSGP.PrimitiveFunction{typeof(Base.:(+))}, Tuple{JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(*))}, JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(+))}, typeof(JuliaGSGP.protected_div)}, JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(-))}, JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(JuliaGSGP.protected_div)}, typeof(Base.:(+))}, typeof(Base.:(-))}, JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(JuliaGSGP.protected_div)}, JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(-))}, typeof(JuliaGSGP.protected_div)}, JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(JuliaGSGP.protected_div)}, JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(*))}, typeof(Base.:(+))}, typeof(JuliaGSGP.protected_div)}}})
precompile(Tuple{Type{JuliaGSGP.FuncNode{T, S, U} where U where S where T}, JuliaGSGP.PrimitiveFunction{typeof(Base.:(*))}, Tuple{JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(-))}, JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(*))}, typeof(Base.:(+))}, JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(+))}, JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(-))}, typeof(JuliaGSGP.protected_div)}}})
precompile(Tuple{Type{JuliaGSGP.FuncNode{T, S, U} where U where S where T}, JuliaGSGP.PrimitiveFunction{typeof(Base.:(+))}, Tuple{JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(*))}, JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(-))}, typeof(Base.:(-))}, JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(-))}, JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(+))}, typeof(Base.:(+))}}})
precompile(Tuple{Type{JuliaGSGP.FuncNode{T, S, U} where U where S where T}, JuliaGSGP.PrimitiveFunction{typeof(JuliaGSGP.protected_div)}, Tuple{JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(-))}, JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(*))}, typeof(Base.:(+))}, JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(+))}, JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(-))}, typeof(JuliaGSGP.protected_div)}, typeof(Base.:(*))}, JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(*))}, JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(-))}, typeof(Base.:(-))}, JuliaGSGP.FuncNode{JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(-))}, JuliaGSGP.FuncNode{JuliaGSGP.Variable{Int64}, JuliaGSGP.Variable{Int64}, typeof(Base.:(+))}, typeof(Base.:(+))}, typeof(Base.:(+))}}})
This compilations slowing down the performance. I think this is because FuncNode
is parameterized by various tree structures, but I’m not sure.
What approach can I take to deal with this problem?