user19242326
user19242326

Reputation:

Writing a function that will take an AbstractVector as its parameter

From Performance Tips:

When working with parameterized types, including arrays, it is best to avoid parameterizing with abstract types where possible.

Suppose you're writing a function that requires a Vector, and with each use of the function, the Vector can contain different types.

function selection_sort!(unsorted_vect::AbstractVector)
    # Code to sort.
end 

names = String["Sarah","Kathy","Amber"]
unsorted_fibonacci = Int32[8, 1, 34, 21, 3, 5, 0, 13, 2, 1]
    
selection_sort!(names)
selection_sort!(unsorted_fibonacci)

When using selection_sort!() the first time, the Vector contains String, the second time Int32.

The function knows it's getting an AbstractVector, but it doesn't know the type of elements.

  1. Will performance be inefficient? Would it be the same as writing selection_sort!(unsorted_vect::AbstractVector{Real})?

The same section also says:

If you cannot avoid containers with abstract value types, it is sometimes better to parametrize with Any to avoid runtime type checking. E.g. IdDict{Any, Any} performs better than IdDict{Type, Vector}

  1. Would it be better to write the function this way?
function selection_sort!(unsorted_vect::AbstractVector{Any})

If so, why do the sorting algorithms just use AbstractVector?

function sort!(v::AbstractVector, # left out other parameters)

Upvotes: 2

Views: 154

Answers (1)

Przemyslaw Szufel
Przemyslaw Szufel

Reputation: 42214

What you need is:

function selection_sort!(unsorted_vect::AbstractVector{T}) where T
    # Code to sort.
end 

In this way you have an abstract type for the container (and hence any container will get accepted). Yet those containers con be non-abstract - because they can have a concrete type for their elements - T. As noted by Bogumil - if in the body code you do not need the type T you could do function selection_sort!(unsorted_vect::AbstractVector) instead.

However, this is just a limit for argument types. Julia would be as happy as to have function selection_sort!(unsorted_vect) and the code would be as efficient.

What will really matter are the types of arguments. Consider the following 3 variables:

a = Vector{Float64}(rand(10))
b = Vector{Union{Float64,Int}}(rand(10))
c = Vector{Any}(rand(10))

a is a typed container, b is a small-union type container and c is an abstract container. Let us have a look on what is happening with the performance:

julia> @btime minimum($a);
  18.530 ns (0 allocations: 0 bytes)

julia> @btime minimum($b);
  28.600 ns (0 allocations: 0 bytes)

julia> @btime minimum($c);
  241.071 ns (9 allocations: 144 bytes)

The variable c requires value unboxing (due to unknown element type) and hence the performance is degraded by an order of magnitude.

In conclusion, it is the parameter type what actually matters.

Upvotes: 1

Related Questions