Understand numpy performance

Viewed 61

I am trying to understand numpy performance using the timeit library.

The codes are just a copy operation

import numpy as np
n = 100
a = np.random.rand(n)
b = np.empty_like(a)
np.copyto(a, b)

I repeated the codes above with different n numbers

def setup(n):
    return f'import numpy as np; a = np.random.randn({int(n)}); b = np.empty_like(a)'

result = []
for n in 2 ** np.arange(18) * 128:
    result.append([
        n,
        *ti.Timer('np.copyto(a, b)', setup(n)).autorange() 
    ])

I ran the codes for 20 times and plotted the result of array length vs time enter image description here It looks OK as expected: the bigger the array length, the longer it takes to copy from a to b. Each colored dot represents each experiment run. The blue line is average of 20 runs.

But when I plotted array length vs throughput (defined as array length / time), I got an unexpected result. enter image description here

The "throughput" increased steadily from array length of 128 till 16384, then it dropped till array length of 131072, then it peaked again at array length of 262144 before diving again.

I ran this 20 times and got the same shape. So the question is why the performance of np.copyto exhibits 2 "peaks" (one at ~ 16384, one at 26144) in the graph of array length vs throughput?

My python is 3.8.5, numpy is 1.9.1

blas_mkl_info:
  NOT AVAILABLE
blis_info:
  NOT AVAILABLE
openblas_info:
    libraries = ['openblas', 'openblas']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None)]
blas_opt_info:
    libraries = ['openblas', 'openblas']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None)]
lapack_mkl_info:
  NOT AVAILABLE
openblas_lapack_info:
    libraries = ['openblas', 'openblas']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None)]
lapack_opt_info:
    libraries = ['openblas', 'openblas']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None)]

lscpu

Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                2
On-line CPU(s) list:   0,1
Thread(s) per core:    1
Core(s) per socket:    2
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 79
Model name:            Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz
Stepping:              1
CPU MHz:               2296.379
BogoMIPS:              4600.10
Hypervisor vendor:     Xen
Virtualization type:   full
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              46080K
NUMA node0 CPU(s):     0,1
0 Answers
Related