Home > Software design >  Numpy fast tiling when shape is the same?
Numpy fast tiling when shape is the same?

Time:04-08

I have the following tiling call in my code.

np.tile(array, (10000, 1))

I call this many times for different arrays, but the shape of those arrays are always the same.

So is there a function that I can define which does this operation faster? For example by pre-generating the shape, and then just filling it up more efficiently with the new array for each call?

CodePudding user response:

You can do the same thing with a 'filling'

For example:

In [92]: arr = np.arange(12).reshape(3,4)
In [93]: np.tile(arr, (5,1))
Out[93]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
In [94]: _.shape
Out[94]: (15, 4)

filling will be easiest if we start with a 3d array, and reshape it:

In [96]: res = np.zeros((5,3,4),arr.dtype)
    ...: res[:] = arr[None,:,:]     # or just res[:] = arr
    ...: res = res.reshape(15,4)
In [97]: 
In [97]: res
Out[97]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

Comparative times:

In [98]: timeit np.tile(arr, (5,1))
9.35 µs ± 13.4 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

In [99]: %%timeit
    ...: res = np.zeros((5,3,4),arr.dtype)
    ...: res[:] = arr[None,:,:]
    ...: res = res.reshape(15,4)
3.6 µs ± 154 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

Or do the reshape in the assignment step, since it's a view:

In [107]: %%timeit
     ...: res = np.zeros((15,4),arr.dtype)
     ...: res.reshape(5,3,4)[:] = arr
2.91 µs ± 131 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

CodePudding user response:

If your arrays are all the same shape, you could collect them into a higher-dimensional array and tile all of them at once. Here's an example with 10 arrays of shape (3, 3):

In [4]: arrs.shape
Out[4]: (10, 3, 3)

In [5]: np.tile(arrs, (1, 10000, 1)).shape
Out[5]: (10, 30000, 3)

Depending on the shape of your arrays, you may need to add more dimensions to the tiling. If you provide a sample array, I can update this answer.

  • Related