Queen
Queen

Reputation: 185

numpy array of zeros or empty

I am writing code and efficiency is very important. Actually I need 2d array, that I am filling with 0 and 1 in for loop. What is better and why?

  1. Make empty array and fill it with "0" and "1". It's pseudocode, my array will be much bigger.

  2. Make array filled by zeros and make if() and if not zero - put one.

So I need information what is more efficiency: 1. Put every element "0" and "1" to empty array or 2. Make if() (efficiency of 'if') and then put only "1" element.

Upvotes: 2

Views: 7621

Answers (4)

bwass31
bwass31

Reputation: 75

In most cases, there is no significant performance difference between np.empty() and np.zeros()

However, np.zeros() may be slightly slower due to the additional step of initializing the allocated memory to zero: 2 * O(n)

Upvotes: 0

BatyaGG
BatyaGG

Reputation: 734

It is better to create array of zeros and fill it using if-else. Even conditions makes slow your code, reshaping empty array or concatenating it with new vectors each iteration of loop is more slower operation, because each time new array of new size is created and old array is copied there together with new vector value by value.

Upvotes: 1

bobflux
bobflux

Reputation: 11591

  • empty() does not initialize the memory, therefore your array will be filled with garbage and you will have to initialize all cells.
  • zeros() initializes everything to 0. Therefore, if your final result includes lots of zeros, this will save you the time to set all those array cells to zero manually.

I would go with zeros(). The performance bottleneck will be your python for loop anyway.

Fortunately, Numpy now as a JIT compiler, which can turn your crummy and slow python for loop into machine code:

http://numba.pydata.org/

I tried it. It's a bit rough around the edges, but the speedups can be quite spectacular compared to bare python code. Of course the best choice is to vectorize using numpy, but you don't always have a choice.

Upvotes: 2

hpaulj
hpaulj

Reputation: 231738

Ae = np.empty(10000)
A0 = np.zeros((10000)

differ slightly in how memory is initially allocated. But any differences in time will be minor if you go on and do something like

for i in range(10000):
    Ae[i] = <some calc>

or

for i in range(10000):
    val = <some calc>
    if val>0:
       A0[i] = val

If I had to loop like this, I'd go ahead and use np.zeros, and also use the unconditional assignment. It keeps the code simpler, and compared to everything else that is going on, the time differences will be minor.


Sample times:

In [33]: def foo0(N):
    ...:     A = np.empty(N,int)
    ...:     for i in range(N):
    ...:         A[i] = np.random.randint(0,2)
    ...:     return A
    ...: 
In [34]: def foo1(N):
    ...:     A = np.zeros(N,int)
    ...:     for i in range(N):
    ...:         val = np.random.randint(0,2)
    ...:         if val:
    ...:             A[i] = val
    ...:     return A
    ...: 

3 ways of assigning 10 0/1 values

In [35]: foo0(10)
Out[35]: array([0, 0, 1, 0, 0, 1, 0, 1, 1, 0])
In [36]: foo1(10)
Out[36]: array([0, 1, 1, 1, 1, 1, 1, 1, 0, 0])
In [37]: np.random.randint(0,2,10)
Out[37]: array([0, 1, 1, 0, 1, 1, 1, 0, 0, 1])

times:

In [38]: timeit foo0(1000)
100 loops, best of 3: 4.06 ms per loop
In [39]: timeit foo1(1000)
100 loops, best of 3: 3.95 ms per loop
In [40]: timeit np.random.randint(0,2,1000)
... cached.
100000 loops, best of 3: 13.6 µs per loop

The 2 loop times are nearly the same.

Upvotes: 1

Related Questions