AFAIU, this βtype instabilityβ is harmless. It is a consequence of the iterator interface which returns nothing when the end of the iterator is reached. Note that the line you cited from the @code_warntype output is colored in yellow (not red, which indicates βtrueβ type instabilities).
Thank @PetrKryslUCSD, eachindex() is a nice tip for this case, but it was a simplified version of my real problem:
function trocar!(V::Array, i::Int, j::Int)
t = V[i]
V[i] = V[j]
V[j] = t
end
function bubblesort!(numeros::Array{T, 1}) where T <: Number
for i = length(numeros):-1:2
for j = 1:i - 1
if (numeros[j] > numeros[j + 1])
trocar!(numeros, j, j + 1)
end
end
end
return numeros
end
The second option without warning that I found was:
function bubblesort_while!(numeros::Array{T, 1}) where T <: Number
i::Int = length(numeros)
while (i >= 2)
j::Int = 1
while (j <= i - 1)
if (numeros[j] > numeros[j + 1])
trocar!(numeros, j, j + 1)
end
j += 1
end
i -= 1
end
return numeros
end
But like @carstenbauer told us, with a warning and without this warning have the same performance.
Replace Array{T, 1} by AbstractVector{T} (or drop it entirely). It is more general and has same performance. Also, drop the ::Int annotations in the code. They are not necessary.
Also, be aware that 1:i - 1 means 1:(i-1) and not (1:i) - 1. Maybe that is what you want (I donβt know). Just wanted to point it out because it might not be obvious.
The suggested algorithm is slower than the code I posted here. I thought that was this syntax, but is the loop suggested at rosettacode.org that is slower.
In a nutshell the best I can do without change the bubble sort algorithm is:
swap!(V::AbstractVector, i::Int, j::Int) = V[i], V[j] = V[j], V[i]
function bubblesort!(numbers::AbstractVector{T}) where T <: Number
for i = length(numbers):-1:2
for j = 1:i - 1
if (numbers[j] > numbers[j + 1])
swap!(numbers, j, j + 1)
end
end
end
return numbers
end
I tried the second way:
function bubblesort2!(numbers::AbstractVector{T}) where T <: Number
for i = length(numbers):-1:2, j = 1:i - 1
if (numbers[j] > numbers[j + 1])
swap!(numbers, j, j + 1)
end
end
return numbers
end
Both functions have same performance.
Can I improve it?
Both functions are the same so it makes sense they have the same performance.
An easy way to increase performance is to tell julia all array indexing operations in the loop are @inbounds (which they are here):
julia> function bubblesort1!(V::AbstractVector{T}) where T <: Number
for i = length(V):-1:2, j = 1:(i-1)
if (V[j] > V[j+1])
V[i], V[j] = V[j], V[i]
end
end
return V
end
julia> @benchmark bubblesort1!(x) setup=x=rand(10000)
BenchmarkTools.Trial:
memory estimate: 0 bytes
allocs estimate: 0
--------------
minimum time: 134.355 ms (0.00% GC)
median time: 136.300 ms (0.00% GC)
mean time: 136.332 ms (0.00% GC)
maximum time: 138.147 ms (0.00% GC)
--------------
samples: 37
evals/sample: 1
julia> function bubblesort2!(V::AbstractVector{T}) where T <: Number
@inbounds for i = length(V):-1:2, j = 1:(i-1)
if (V[j] > V[j+1])
V[i], V[j] = V[j], V[i]
end
end
return V
end
bubblesort2! (generic function with 1 method)
julia> @benchmark bubblesort2!(x) setup=x=rand(10000)
BenchmarkTools.Trial:
memory estimate: 0 bytes
allocs estimate: 0
--------------
minimum time: 120.128 ms (0.00% GC)
median time: 121.617 ms (0.00% GC)
mean time: 121.776 ms (0.00% GC)
maximum time: 125.037 ms (0.00% GC)
--------------
samples: 42
evals/sample: 1