Hello,
I started using Julia intensively a few months ago, and I keep coming across situations where I have vectors of abstract types, which should be avoided for performance reasons. I can’t seem to find satisfying solutions to these situations.
Here is a simplified example of the last time I had this problem:
I’m doing some machine learning experiments, during which I log several metrics, which number and type can differ between experiments. For this, I define an AbstractMetric
abstract type, and, for each metric, one concrete type I can dispatch on. For example:
# Abstract type
abstract type AbstractMetric end
function log!(m::AbstractMetric; kwargs...)
push!(m.history, m(kwargs...))
end
# Loss concrete types
struct Loss <: AbstractMetric
history::Vector{Float64}
end
Loss() = Loss(Float64[])
function (m::Loss)(; loss, groundtruths, predictions, kwargs...)
return sum(loss(y, y_pred) for (y, y_pred) in zip(groundtruths, predictions))
end
# Accuracy concrete type
struct Accuracy <: AbstractMetric
history::Vector{Float64}
end
Accuracy() = Loss(Float64[])
function (m::Accuracy)(; groundtruths, predictions, kwargs...)
return mean(y == y_pred for (y, y_pred) in zip(groundtruths, predictions))
end
# Other metrics
...
I store all the current metrics in a vector and use a for loop calling the log!
method.
Problem: the vector is a Vector{AbstractMetric}
.
Is there a better implementation that can avoid that ?