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?