6.2. Ndarray

ndarray je typ, který v numpy uchovává numerická data. Je to dvě věci v jednom: jediný kompaktní blok dat a malý deskriptor před tímto blokem, který říká, jak jej číst.

6.2.1. Uvnitř krabice

Datový blok obsahuje všechny prvky pole jeden za druhým, bez čehokoli navíc mezi nimi. Každý prvek zabírá stejný počet bajtů – jeden u pole hodnot uint8, dva u uint16, čtyři u float. 256prvkové pole uint8 je přesně 256 bajtů dat; stejných 256 čísel v Python list zabere kilobajt – jeden 32bitový slot na prvek bez ohledu na to, jak málo bitů hodnota ve skutečnosti potřebuje.

Deskriptor zaznamenává, co blok znamená. Pět hodnot stačí k popisu libovolného obdélníkového pole bez ohledu na počet rozměrů:

  • dtype – typ prvku. Rozhoduje o tom, kolik bajtů každý prvek zabírá a jaký rozsah hodnot může uchovávat (probráno na stránce Dtypy).

  • itemsize – šířka jednoho prvku v bajtech, odvozená z dtype.

  • ndim – počet rozměrů (1 pro vektor, 2 pro matici, 3 pro objem, až do 4).

  • shape – velikost podél každého rozměru jako n-tice.

  • strides – jak procházet datovým blokem při průchodu každou osou. Probráno na stránce Tvar a kroky.

A to je vše. Každá rychlá cesta v numpy – aritmetika, redukce, broadcasting, řezy – pracuje přímo z těchto pěti hodnot a ukazatele na data, bez režie Pythonu na jednotlivé prvky.

6.2.2. Co tento návrh přináší

Z konceptu „kompaktní blok + malý deskriptor“ vyplývají tři vlastnosti, které definují, jak se chová zbytek této sekce.

Matematika po prvcích běží jako jediné volání. a + b mezi dvěma poli shodného tvaru sečte dva buffery a zapíše třetí, a to vše uvnitř jednoho volání knihovny. np.sin(a) udělá totéž pro sinus každého prvku. Aritmetické, porovnávací a bitové operátory fungují všechny tímto způsobem.

Pohled na stejná data jiným způsobem je zdarma. Žádost o podoblast pole nebo o tatáž data uspořádaná pod jiným tvarem nepřesouvá žádné bajty. Operace vrátí nový deskriptor ukazující na tentýž datový blok. Výsledek se nazývá pohled (view) – druhé okno do téhož podkladového bufferu. Zápis přes pohled zapisuje do zdroje.

Smíšené tvary stále fungují. Kratší pole proti delšímu, řádek proti matici, sloupec proti řádku – numpy je srovná pomocí broadcastingu, malé sady pravidel, která rozhodují, která krátká osa se roztáhne, aby odpovídala dlouhé. Roztažení je virtuální; žádná data se neduplikují.

6.2.3. Co tento návrh stojí

Ze stejného návrhu vyplývají dvě omezení.

Každý prvek má stejný typ. Seznam může obsahovat int vedle str vedle seznamu tří dalších hodnot int; ndarray nemůže. Dtype je pevně dán v době konstrukce. Stránka Dtypy probírá malou sadu typů, které numpy podporuje, a pravidla, jež vyplývají z toho, že je typ pevně daný.

Zvětšení pole není zdarma. Seznam si na konci ponechává volné sloty a levně podporuje .append. ndarray má přesně takovou velikost, jakou potřebuje; přidání by znamenalo alokovat nový, větší buffer a zkopírovat do něj starý obsah. Metoda append() záměrně neexistuje. Správným vzorem na kameře je předalokovat cíl na jeho konečnou velikost a naplnit jej; stránka Výkon tuto techniku probírá.

S kompaktním typovaným bufferem pro data, malým deskriptorem pro metadata a třemi zárukami chování (rychlá matematika po prvcích, alternativní pohledy na stejná data bez kopírování a tvary, které se broadcastují) je ndarray základem, na němž stojí zbytek této kapitoly. Jak pole vlastně vzniká – z literálu, z předvyplněné alokace, z bufferu periferie – je další praktická otázka.