6.5. Shape dan strides

Data di dalam ndarray adalah satu blok angka yang padat. Deskriptor di depan blok tersebut memutuskan bagaimana blok datar itu dibaca sebagai tensor.

6.5.1. Apa yang dicatat deskriptor

Lima nilai mendeskripsikan cara membaca blok data sebagai tensor:

a = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint8)

a.ndim       # 2     - number of dimensions
a.shape      # (2, 3)- length along each dimension
a.itemsize   # 1     - bytes per element (from dtype)
a.size       # 6     - total number of elements
a.strides    # (3, 1)- step pattern through the buffer

Helper ndinfo() mencetak semuanya ditambah lokasi buffer yang mendasari dalam satu panggilan. Dua array yang lokasi buffernya cocok berbagi memori:

np.ndinfo(a)
# class: ndarray
# shape: (2, 3)
# strides: (3, 1)
# itemsize: 1
# data pointer: 0x...
# type: uint8

6.5.2. Penjelasan strides

Sebuah stride adalah berapa banyak byte untuk melangkah dalam blok data guna berpindah satu elemen sepanjang sumbu tertentu. Untuk array uint8 2x3 di atas, stride-nya adalah (3, 1): berpindah satu baris ke bawah melompati 3 byte, berpindah satu kolom ke kanan melompati 1 byte. Itu sama dengan mengatakan baris disimpan berurutan, kiri ke kanan:

memory: [ 1 ][ 2 ][ 3 ][ 4 ][ 5 ][ 6 ]
          ^ row 0          ^ row 1
          <------- 3 bytes ---->

Untuk membaca a[i, j], numpy menghitung i * strides[0] + j * strides[1] dari awal blok data dan membaca itemsize byte dari sana. Rumus yang sama berlaku untuk jumlah dimensi berapa pun.

Tata letak ini -- baris disimpan ujung ke ujung, dengan sumbu terakhir bervariasi paling cepat sepanjang memori -- disebut urutan row-major. Setiap array yang numpy alokasikan pada kamera menggunakan tata letak ini.

6.5.3. Konsekuensi row-major

Dua hal mengikuti dari "baris disimpan berurutan" yang penting saat membentuk buffer pada kamera.

Sumbu terakhir bersifat kontinu. Berjalan dari a[0, 0] ke a[0, 1] menyentuh byte berikutnya. Berjalan dari a[0, 0] ke a[1, 0] melompati seluruh baris.

Sumbu terakhir adalah sumbu cepat untuk matematika seluruh-array. numpy pada kamera selalu berjalan pada sumbu terakhir paling dalam, terlepas dari sumbu mana yang kebetulan lebih panjang. Library numpy desktop secara diam-diam menyusun ulang loop-nya untuk menempatkan sumbu terpanjang paling dalam; kamera tidak melakukan itu, sehingga pilihan tata letak yang desktop numpy tutupi masih membutuhkan waktu di sini. np.sum(m, axis=1) meruntuhkan sumbu terakhir dan berjalan dalam arah kontinu; np.sum(m, axis=0) tidak. Ketika aplikasi memiliki pilihan tentang bagaimana menata buffer, letakkan sumbu panjang terakhir agar operasi di sepanjangnya tetap berada di loop dalam.

Jika tata letaknya mulai salah, transpose() (atau pintasan .T) memperbaikinya tanpa menyalin data -- hanya menukar stride:

a = b.T            # now iterates fast

Performa memiliki diskusi performa lengkap.

6.5.4. Reshape, transpose, slicing -- pengeditan deskriptor

Operasi apa pun yang hanya menulis ulang deskriptor adalah gratis. reshape menukar shape dan strides baru di blok data yang sama. transpose membalik stride. a[::2] menggandakan stride. Setiap mengembalikan view dari buffer yang mendasari yang sama.

Apa pun yang harus menelusuri data dan menulis buffer baru adalah copy. Aturan untuk saat ini adalah bahwa pengeditan deskriptor gratis dan penelusuran data tidak.

6.5.5. Catatan tentang ndim

numpy pada kamera dibangun dengan ndim maksimum yang didukung sebesar 4. Operasi yang akan menghasilkan array berperingkat lebih tinggi memunculkan ValueError. Sebagian besar pekerjaan sisi kamera adalah 1-D atau 2-D, sehingga batasannya jarang menjadi masalah.