Dealing with a type-unstable output variable

What we haven't noticed is another type instability problem concerning the accumulator. In the preceding example, the double_sum function has a total variable that keeps track of the doubled numbers. The problem is that the variable was defined as an integer, but then the array may contain floating-pointer numbers instead. This problem can be easily revealed by running @code_warntype against both scenarios.

Here is the output of @code_warntype for when an array of integers is passed into the function:

Compare it with the output when an array of Float64 is passed:

If we call the function with an array of integers, then the type is stable. If we call the function with an array of floats, then we see the type instability issue.

How do we fix this? Well, there are standard Base functions for creating type-stable zeros or ones. For example, rather than hardcoding the initial value of total to be an integer zero, we can do the following instead:

function double_sum(data)
total = zero(eltype(data))
for v in data
total += 2 * v
end
return total
end

If we look into the @code_warntype output of the double_sum_of_random_data function, it is much better than before. I will let you do this exercise and compare the @code_warntype output with the prior one.

A similar solution makes use of the parametric method:

function double_sum(data::AbstractVector{T}) where {T <: Number}
total = zero(T)
for v in data
total += v
end
return total
end

The T  type parameter is used to initialize the total variable to the properly typed value of zero.

This kind of performance gotcha is sometimes difficult to catch. To ensure optimized code is generated, it is always a good practice to use the following functions for an accumulator or an array that stores output values:

  • zero and zeros create a value of 0 or an array of 0s for the desired type.
  • one and ones create a value of 1 or an array of 1s for the desired type.
  • similar creates an array of the same type as the array argument.

For example, we can create a value of 0 or an array of 0s for any numeric types as follows:

Likewise, the one and ones functions work the same way:

If we want to create an array that looks like another one (in other words, has the same type, shape, and size), then we can use the similar function:

Note that the similar function does not zero out the content of the array.

The axes function may come in handy when we need to create an array of zeros that matches the same dimensions of another array:

Next, we will look into a way to debug type instability issues.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.202.54