I got curious and timed it. numpy.sum seems much faster for numpy arrays, but much slower on lists.

import numpy as np
import timeit

x = range(1000)
# or 
#x = np.random.standard_normal(1000)

def pure_sum():
    return sum(x)

def numpy_sum():
    return np.sum(x)

n = 10000

t1 = timeit.timeit(pure_sum, number = n)
print 'Pure Python Sum:', t1
t2 = timeit.timeit(numpy_sum, number = n)
print 'Numpy Sum:', t2

Result when x = range(1000):

Pure Python Sum: 0.445913167735
Numpy Sum: 8.54926219673

Result when x = np.random.standard_normal(1000):

Pure Python Sum: 12.1442425643
Numpy Sum: 0.303303771848

I am using Python 2.7.2 and Numpy 1.6.1

Answer from Akavall on Stack Overflow
Top answer
1 of 6
88

I got curious and timed it. numpy.sum seems much faster for numpy arrays, but much slower on lists.

import numpy as np
import timeit

x = range(1000)
# or 
#x = np.random.standard_normal(1000)

def pure_sum():
    return sum(x)

def numpy_sum():
    return np.sum(x)

n = 10000

t1 = timeit.timeit(pure_sum, number = n)
print 'Pure Python Sum:', t1
t2 = timeit.timeit(numpy_sum, number = n)
print 'Numpy Sum:', t2

Result when x = range(1000):

Pure Python Sum: 0.445913167735
Numpy Sum: 8.54926219673

Result when x = np.random.standard_normal(1000):

Pure Python Sum: 12.1442425643
Numpy Sum: 0.303303771848

I am using Python 2.7.2 and Numpy 1.6.1

2 of 6
87

[...] my [...] question here is would using numpy.sum on a list of Python integers be any faster than using Python's own sum?

The answer to this question is: No.

Pythons sum will be faster on lists, while NumPys sum will be faster on arrays. I actually did a benchmark to show the timings (Python 3.6, NumPy 1.14):

import random
import numpy as np
import matplotlib.pyplot as plt

from simple_benchmark import benchmark

%matplotlib notebook

def numpy_sum(it):
    return np.sum(it)

def python_sum(it):
    return sum(it)

def numpy_sum_method(arr):
    return arr.sum()

b_array = benchmark(
    [numpy_sum, numpy_sum_method, python_sum],
    arguments={2**i: np.random.randint(0, 10, 2**i) for i in range(2, 21)},
    argument_name='array size',
    function_aliases={numpy_sum: 'numpy.sum(<array>)', numpy_sum_method: '<array>.sum()', python_sum: "sum(<array>)"}
)

b_list = benchmark(
    [numpy_sum, python_sum],
    arguments={2**i: [random.randint(0, 10) for _ in range(2**i)] for i in range(2, 21)},
    argument_name='list size',
    function_aliases={numpy_sum: 'numpy.sum(<list>)', python_sum: "sum(<list>)"}
)

With these results:

f, (ax1, ax2) = plt.subplots(1, 2, sharey=True)
b_array.plot(ax=ax1)
b_list.plot(ax=ax2)

Left: on a NumPy array; Right: on a Python list. Note that this is a log-log plot because the benchmark covers a very wide range of values. However for qualitative results: Lower means better.

Which shows that for lists Pythons sum is always faster while np.sum or the sum method on the array will be faster (except for very short arrays where Pythons sum is faster).

Just in case you're interested in comparing these against each other I also made a plot including all of them:

f, ax = plt.subplots(1)
b_array.plot(ax=ax)
b_list.plot(ax=ax)
ax.grid(which='both')

Interestingly the point at which numpy can compete on arrays with Python and lists is roughly at around 200 elements! Note that this number may depend on a lot of factors, such as Python/NumPy version, ... Don't take it too literally.

What hasn't been mentioned is the reason for this difference (I mean the large scale difference not the difference for short lists/arrays where the functions simply have different constant overhead). Assuming CPython a Python list is a wrapper around a C (the language C) array of pointers to Python objects (in this case Python integers). These integers can be seen as wrappers around a C integer (not actually correct because Python integers can be arbitrarily big so it cannot simply use one C integer but it's close enough).

For example a list like [1, 2, 3] would be (schematically, I left out a few details) stored like this:

A NumPy array however is a wrapper around a C array containing C values (in this case int or long depending on 32 or 64bit and depending on the operating system).

So a NumPy array like np.array([1, 2, 3]) would look like this:

The next thing to understand is how these functions work:

  • Pythons sum iterates over the iterable (in this case the list or array) and adds all elements.
  • NumPys sum method iterates over the stored C array and adds these C values and finally wraps that value in a Python type (in this case numpy.int32 (or numpy.int64) and returns it.
  • NumPys sum function converts the input to an array (at least if it isn't an array already) and then uses the NumPy sum method.

Clearly adding C values from a C array is much faster than adding Python objects, which is why the NumPy functions can be much faster (see the second plot above, the NumPy functions on arrays beat the Python sum by far for large arrays).

But converting a Python list to a NumPy array is relatively slow and then you still have to add the C values. Which is why for lists the Python sum will be faster.

The only remaining open question is why is Pythons sum on an array so slow (it's the slowest of all compared functions). And that actually has to do with the fact that Pythons sum simply iterates over whatever you pass in. In case of a list it gets the stored Python object but in case of a 1D NumPy array there are no stored Python objects, just C values, so Python&NumPy have to create a Python object (an numpy.int32 or numpy.int64) for each element and then these Python objects have to be added. The creating the wrapper for the C value is what makes it really slow.

Additionally, what are the implications (including performance) of using a Python integer versus a scalar numpy.int32? For example, for a += 1, is there a behavior or performance difference if the type of a is a Python integer or a numpy.int32?

I made some tests and for addition and subtractions of scalars you should definitely stick with Python integers. Even though there could be some caching going on which means that the following tests might not be totally representative:

from itertools import repeat

python_integer = 1000
numpy_integer_32 = np.int32(1000)
numpy_integer_64 = np.int64(1000)

def repeatedly_add_one(val):
    for _ in repeat(None, 100000):
        _ = val + 1

%timeit repeatedly_add_one(python_integer)
3.7 ms ± 71.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit repeatedly_add_one(numpy_integer_32)
14.3 ms ± 162 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit repeatedly_add_one(numpy_integer_64)
18.5 ms ± 494 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


def repeatedly_sub_one(val):
    for _ in repeat(None, 100000):
        _ = val - 1

%timeit repeatedly_sub_one(python_integer)
3.75 ms ± 236 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit repeatedly_sub_one(numpy_integer_32)
15.7 ms ± 437 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit repeatedly_sub_one(numpy_integer_64)
19 ms ± 834 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

It's 3-6 times faster to do scalar operations with Python integers than with NumPy scalars. I haven't checked why that's the case but my guess is that NumPy scalars are rarely used and probably not optimized for performance.

The difference becomes a bit less if you actually perform arithmetic operations where both operands are numpy scalars:

def repeatedly_add_one(val):
    one = type(val)(1)  # create a 1 with the same type as the input
    for _ in repeat(None, 100000):
        _ = val + one

%timeit repeatedly_add_one(python_integer)
3.88 ms ± 273 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit repeatedly_add_one(numpy_integer_32)
6.12 ms ± 324 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit repeatedly_add_one(numpy_integer_64)
6.49 ms ± 265 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Then it's only 2 times slower.


In case you wondered why I used itertools.repeat here when I could simply have used for _ in range(...) instead. The reason is that repeat is faster and thus incurs less overhead per loop. Because I'm only interested in the addition/subtraction time it's actually preferable not to have the looping overhead messing with the timings (at least not that much).

🌐
NumPy
numpy.org › doc › stable › reference › generated › numpy.sum.html
numpy.sum — NumPy v2.5 Manual
For floating point numbers the numerical precision of sum (and np.add.reduce) is in general limited by directly adding each number individually to the result causing rounding errors in every step. However, often numpy will use a numerically better approach (partial pairwise summation) leading to improved precision in many use-cases.
Discussions

Question about output regarding sum() vs np.array()
sum(some_iterable) will add together the elements of the iterable. In the case of numpy arrays of integers, I believe this will result in something like a numpy.int32 style of integer, but I'm not at my computer to check. You can check by simply printing type(your_thing). np.array will not add anything together. It will create a numpy array. However, you can add an integer to a numpy array - this results in adding that integer to every element of the array. Eg: print(np.array([1, 2, 3]) + 1) As for best practice: In general when you're using numpy, use numpy versions of everything you possibly can, at all times, always. Do not use for loops unless you absolutely have to. If you think you have to, you're probably wrong. Do not use python's sum (this is a hidden-ish for loop), use np.sum (or your_array.sum). It's ok to use operators such as +, -, *, /, @, &, and |, because doing so will invoke the numpy functions that do those things. The why is because numpy is compiled to machine code, is fast, vectorized, and is often multithreaded as well. Pure python can not compete in terms of performance. So: given two solutions, one of which uses numpy functions and one of which uses python builtin things like sum, prefer the numpy version. More on reddit.com
🌐 r/learnpython
4
2
January 27, 2024
Difference between sum, 'sum' and np.sum *under the hood* (Python / Pandas / Numpy) - Stack Overflow
How do, sum, 'sum' and np.sum differ, under the bonnet, here: More on stackoverflow.com
🌐 stackoverflow.com
numpy.sum and python's sum giving different results on a 1-d numpy array
There was an error while loading. Please reload this page · I'm wondering why the code More on github.com
🌐 github.com
7
February 17, 2017
python - What is the difference between np.sum and np.add.reduce? - Stack Overflow
np.sum (without specifying the axis) will return the sum of all elements in the matrix. np.add.reduce (without specifying the axis) will return the sum along axis=0. More on stackoverflow.com
🌐 stackoverflow.com
🌐
DEV Community
dev.to › adityaberi8 › what-to-use-python-s-sum-or-numpy-s-np-sum-2ffj
Python's Sum or NumPy's np.sum() ???I found a big difference in time!! - DEV Community
May 4, 2020 - According to me Use python's methods (sum()) on python datatypes and use NumPy's methods on NumPy arrays (np.sum()).
🌐
Reddit
reddit.com › r/learnpython › question about output regarding sum() vs np.array()
r/learnpython on Reddit: Question about output regarding sum() vs np.array()
January 27, 2024 -

# d_max: day(s) of month m in which m_max inches fell
d_max = np.where(md >= m_max) # mask every index value that had max rainfall
d_max = sum(d_max)
d_max = d_max + 1 # +1 to index outputs date
print(d_max)

[18]

I came up with this solution but the answer key is using np.array where I'm using sum(). It yields the same, correct answer (18) but I'm not sure why. If I omit the sum() function, I can't add 1 to d_max.

Does sum() convert a variable to an integer? Does np.array also convert it to an integer? Just trying to understand which is the correct or better function to use in this case.

🌐
Google Groups
groups.google.com › g › cython-users › c › 7zlP_j5Rd7w
performance of Python's `sum` vs `np.sum` vs writing a naive sum
April 10, 2016 - In [1]: import numba as nb In [2]: @nb.jit(nopython=True) ...: def sumr(i): ...: s=0 ...: for x in range(i): ...: s+=x ...: return s In [3]: r1=sum(range(int(1e6))) In [4]: r2=sumr(int(1e6)) In [5]: import numpy as np In [6]: r3=np.sum(np.arange(0,int(1e6))) In [7]: r1==r2 Out[7]: True In [8]: r3==r2 Out[8]: True In [9]: %timeit r1=sum(range(int(1e6))) 10 loops, best of 3: 37.3 ms per loop In [10]: %timeit r2=sumr(int(1e6)) The slowest run took 17.59 times longer than the fastest.
🌐
Medium
medium.com › @chanushkr › understanding-normal-sum-vs-cumulative-sum-in-numpy-ae5b8c94026f
Understanding Normal Sum vs. Cumulative Sum in NumPy 🧮🔍 | by Chanush KR | Medium
July 23, 2024 - What is Normal Sum? ➕💡 The normal sum is the total sum of all the elements in an array. It provides a single scalar value that represents the sum of the array’s elements. In NumPy, you can compute the normal sum using the np.sum() function ...
Find elsewhere
🌐
Quora
quora.com › What-is-the-difference-between-numpy-add-and-numpy-sum
What is the difference between numpy.add() and numpy-sum()? - Quora
Answer: Thanks for A2A! Short Answer: numpy.add() is used to add two arrays element wise whereas numpy.sum() returns the sum of all elements in an array. Long Answer: Let us look at the official documentation [1] for their description. 1. numpy.add() - Add arguments element-wise. [2] 2. numpy...
🌐
GitHub
github.com › numpy › numpy › issues › 8632
numpy.sum and python's sum giving different results on a 1-d numpy array · Issue #8632 · numpy/numpy
February 17, 2017 - I'm wondering why the code import numpy x = numpy.zeros(10)+0.1 print(sum(x) == numpy.sum(x)) prints False. I realize this is something to do with floating point / roundoff errors, but I'm surprised numpy.sum and sum behave differently i...
Author: numpy
🌐
W3Schools
w3schools.com › python › numpy › numpy_ufunc_summations.asp
NumPy ufuncs - Summations
Addition is done between two arguments whereas summation happens over n elements. ... import numpy as np arr1 = np.array([1, 2, 3]) arr2 = np.array([1, 2, 3]) newarr = np.add(arr1, arr2) print(newarr) Try it Yourself »
🌐
GeeksforGeeks
geeksforgeeks.org › numpy-sum-in-python
numpy.sum() in Python - GeeksforGeeks
August 28, 2024 - Sum of arr : 279 Sum of arr(uint8) : 23 Sum of arr(float32) : 279.0 Is np.sum(arr).dtype == np.uint : False Is np.sum(arr).dtype == np.float : False ... This Python program uses numpy.sum() to compute the sum of elements in a 2D array.
🌐
NumPy
numpy.org › devdocs › reference › generated › numpy.sum.html
numpy.sum — NumPy v2.6.dev0 Manual
For floating point numbers the numerical precision of sum (and np.add.reduce) is in general limited by directly adding each number individually to the result causing rounding errors in every step. However, often numpy will use a numerically better approach (partial pairwise summation) leading to improved precision in many use-cases.
🌐
Medium
medium.com › towards-data-science › understanding-numpy-sum-1587eec69527
Understanding NumPy sum. If you are not clear on what NumPy is… | by Kshitij Bajracharya | TDS Archive | Medium
August 20, 2018 - So when it collapses the axis 0 (row), it becomes just one row and column-wise sum. Let’s see what that means. Now, it can get a little confusing in 2D, so let’s understand this first in a higher dimension and then we’ll step it down into 2D; much like what she did in her post. So, let’s take a 3D array with a shape of (4,3,2). three_d_array = np.arange(24).reshape(4,3,2) three_d_array now becomes equal to ·
🌐
Sharp Sight
sharpsight.ai › blog › numpy-sum
How to Use the Numpy Sum Function - Sharp Sight
February 6, 2024 - This might sound a little confusing, so think about what np.sum is doing. When NumPy sum operates on an ndarray, it’s taking a multi-dimensional object, and summarizing the values. It either sums up all of the values, in which case it collapses down an array into a single scalar value.
🌐
DigitalOcean
digitalocean.com › community › tutorials › numpy-sum-in-python
numpy.sum() in Python | DigitalOcean
Technical tutorials, Q&A, events — This is an inclusive place where developers can find or lend support and discover new ways to contribute to the community.