Table of Contents
What are Universal Functions?
This course is concerned with the use of a certain class of built-in functions in NumPy called Universal Functions (ufuncs) to perform operations on arrays efficiently. In addition to the basic arithmetic operations such as division and power, ufuncs also include transcendental functions such as trigonometric, logarithmic, exponential and even special functions.
The key to NumPy’s speed in performing such operations is the use of vectorized operations, generally implemented through NumPy’s ufuncs. Vectorization makes repeated calculations on array elements much more efficient.
An Example of Vectorization
Imagine we have an array of random integer values and would like to compute the reciprocal of each element. We employ two methods:
- conventional Python method using a loop
- using NumPy vectorization
We first import the NumPy package, define a Python function to compute the reciprocal of an array and generate an array of random integers using the randint
function.
1import numpy as np
2
3def compute_reciprocals(values):
4 s = values.size
5 output = np.empty(s)
6 for i in range(s):
7 output[i] = 1.0 / values[i]
8 return output
9
10R = np.random.RandomState(18) #set a random seed
11values = R.randint(1, 10, size=10)
12print(values) # random integers
[4 9 6 2 3 3 9 9 3 2]
Example
Compute the reciprocals of an array using a loop.1print(compute_reciprocals(values)) # reciprocals
[0.25 0.11111111 0.16666667 0.5 0.33333333 0.33333333
0.11111111 0.11111111 0.33333333 0.5 ]
Example
Compute the reciprocal of an array using NumPy ufunc.1print(1.0 / values)
[0.25 0.11111111 0.16666667 0.5 0.33333333 0.33333333
0.11111111 0.11111111 0.33333333 0.5 ]
ADVERTISEMENT
Timing the Vectorization
We now create a large random array and compare the execution times of the two different methods.
Example
Timing the execution: Python loop vs NumPy ufunc.1arr = R.randint(1, 10, size=1000)
2%timeit compute_reciprocals(arr)
3%timeit (1.0 / arr) # using vectorization
1.79 ms ± 6.47 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
2.11 µs ± 66.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
We see that the vectorized operation is around 3 orders of magnitude faster than the Python loop.