# coding: utf-8 # # How are numpy arrays stored? # In[1]: import numpy as np # Numpy presents an n-dimensional abstraction that has to be fit into 1-dimensional computer memory. # # Even for 2 dimensions (matrices), this leads to confusion: row-major, column-major. # In[4]: A = np.arange(9).reshape(3, 3) print(A) # ## Strides and in-memory representation # How is this represented in memory? # In[6]: A.strides # * `strides` stores for each axis by how many bytes one needs to jump to get from one entry to the next (in that axis) # * So how is the array above stored? # * This captures row-major ("C" order) and column-major ("Fortran" order), but is actually much more general. # We can also ask for Fortran order: # In[10]: A2 = np.arange(9).reshape(3, 3, order="F") A2 # `numpy` defaults to row-major order. # In[11]: A2.strides # ## Strides and Contiguity # How is the stride model more general than just saying "row major" or "column major"? # In[15]: A = np.arange(16).reshape(4, 4) A # In[18]: A.strides # In[14]: Asub = A[:3, :3] Asub # Recall that `Asub` constitutes a *view* of the original data in `A`. # In[19]: Asub.strides # Now `Asub` is no longer a *contiguous* array! # # From the linear-memory representation (as show by the increasing numbers in `A`) 3, 7, 11 are missing. # # This is easy to check by a flag: # In[20]: Asub.flags