NumPy — Why is it so fast?

Yudhishthir Singh
The Startup
Published in
5 min readJun 6, 2020

Thinking of switching your career into Data Science and have no idea where to start, what to learn, what is important? If you have any (literally, any) knowledge of python, trust me first stepping stone is to get familiar with the python library called NumPy.

Introduction:

NumPy is considered to be a fundamental package for all scientific computing in python. It is used for working with arrays — single & multi-dimensional, It also contains functions for mathematical computations such as linear algebra, matrices, etc.

When you are dealing with data, most of the time you are dealing with arrays. For Software Development and other fields that do not have so many dependencies on data and it’s size, it’s okay to go with normal python lists. But when you are playing with huge datasets, python lists can prove to be really slow and inefficient. NumPy shines here, it takes a significantly less amount of memory as compared to python lists.

Other than being speed and memory efficient, NumPy has another great advantage that it works well with major libraries such as SciPy, MatPlotLib, Pandas.

Why is it fast?

First, let me prove that it is indeed fast. Then we will delve into why is it so!

I will try to find the sum of all numbers from 0–1 billion using core python and then using NumPy.

For core python, I will use the range() function to generate numbers from 0 to 1 billion, then will use the sum() function to find out the sum.

For NumPy I will use the arange() function, which does the same thing as the range() function, then I will use the .sum() function provided by NumPy.

  1. Without NumPy:
import time

start_time = time.time()
count = 1000000000 # one billion

normalRange = range(count)
print(sum(normalRange))

print("Time taken: %s seconds" % (time.time() - start_time))

Below is the result, It took around 15 seconds to find the sum.

2. With NumPy:

import time
import numpy as np

start_time = time.time()
count = 1000000000 # one billion

numpyRange = np.arange(count)
print(numpyRange.sum())

print("Time taken: %s seconds" % (time.time() - start_time))

With NumPy, it took around 10 seconds to find the sum.

This was just a general test and 5 seconds might not sound very exciting, but trust me it means a lot. There are plenty of benchmarks available to prove how fast NumPy is.

Back to the question, Why is it fast?

NumPy arrays are faster because of several factors. Python is a dynamic language that is interpreted by a CPython interpreter, converted to bytecode, and then executed. Whereas NumPy itself is written in C, which is the main result of its faster execution time.

Apart from being written in C, its memory allocation is far better than that of a normal list in python. Let’s look at this in detail, How NumPy arrays are allocated space in memory that makes them faster.

  1. Type of element:

Let’s try to understand how the arrays are stored on your computer. Suppose you have an array like -> arr = [1,2,3,4,5]. Take any number from the array, let’s say 5.

Let’s see how this element 5 will be stored in a NumPy array, and then we will see how it is stored in a normal python list.

In case of NumPy, this element will not go inside the array as the type int (Python built-in data type). Instead. Your computer will look at this 5 in binary as 00000101 (which is one byte). This one byte will, by default, will be casted into int32 which is 4 bytes and stored into the memory as:

00000000 00000000 00000000 00000101

With NumPy, You can specify that the default value given by computer (4 bytes) is not what you actually need, and instead just need 1 byte to store the item. By 1 byte, I mean int8. When converted from int32 to int8, the same item, 5, will look as:

00000101

And that’s all, this is how the element 5 from that array will be stored in the case of NumPy.

On the other hand, The process of storing the same element 5 from the array will be far more expensive with normal Python Lists as there is too much extra information that needs to be stored in the computer’s memory apart from the element itself. When the element 5 goes inside a python list, goes as a built-in int type. This int type consists of four different things: Size, Reference Count, Object Type, Object Value. Apart from Size, all other stated info is stored as Long (8 bytes), and the size itself is 4 bytes. So in total 28 bytes, which is far more space than the NumPy array element.

2. No type checking needing while reading the array.

In the case of a normal python list, items can be of various types either a string or a bool or an int. So the compiler has to check for each element that comes out of it. On the other hand, in the case of NumPy array, all the elements are of the same type which helps in faster reading.

3. Element are stored in Contiguous Memory locations in NumPy.

The items inside a NumPy array are stored next to each other in the memory which is another reason for it being fast. The diagram below illustrated how an array [1,2,3,4,5] will be stored in NumPy:

On the other hand, Elements of python lists are not necessarily next to each other in the computer’s memory. The list that you create just holds references to the actual locations of those elements.

This was all, these factors make NumPy really efficient and make our lives easier.

I hope you were able to figure out why is NumPy faster than the normal arrays and are motivated enough to put it to use in your daily life.

To learn more about NumPy, head on to the official documentation here:

If you found this article insightful, do hit the clap 👏 button. (Don’t forget you can hit it for 50 times!)

Happy Coding!

--

--