6.1. Neden diziler¶
Image sınıfı, piksel işleri için doğru araçtır çünkü üzerindeki her yöntem, kameranın yerel piksel arabelleği üzerinde doğrudan, tek bir hızlı çağrıyla çalışır. Uygulamanın bir çerçeveye yaptığı işlerin çoğu – eşikleme, nokta bulma, AprilTag tespiti, kenar filtreleri – zaten orada bulunur.
Görüntü kütüphanesinin açığa çıkarmadığı şey, bir OpenMV uygulamasının karşılaştığı sayısal işlerin geri kalanıdır:
piksel olmayan sensör arabellekleri – ADC örnekleri, bir IMU‘dan (atalet ölçüm birimi) eksenler, mikrofon sesi,
görüntüden türetilen ve hiçbir yerleşik yöntemin döndürmediği sayılar – bir histogram sütunu, iki çerçevenin özel bir karışımı, kataloğun kapsamadığı piksel başına bir dönüşüm,
küçük doğrusal cebir – merceği düzelten kalibrasyon matrisi, IMU’yu birleştiren döndürme,
sinyal işleme matematiği – bir titreşim arabelleğinin frekans içeriği, bir sensörün çıktısına uygulanan yumuşatma, bir sınıflandırıcının girdi olarak istediği bir öznitelik vektörü.
Bunların hepsi aynı biçimi ister: her elemanına bir işlem uygulanmış bir sayı arabelleği. Bir Python for döngüsü, bunu yazmanın bariz yoludur:
for i in range(len(samples)):
samples[i] = samples[i] * cal
Döngü çalışır. Ama aynı zamanda yavaştır. Python yorumlanan bir dildir ve bir Python döngüsünün her yinelemesi, yorumlayıcıyı bir kez çalıştırmanın maliyetini taşır: samples‘ı ara, i elemanını oku, çarp, geri yaz, döngü sayacını ilerlet, döngü koşulunu kontrol et. Bin sensör örneğinden oluşan bir arabellekte, bu yorumlayıcı maliyetleri, aslında hızlı olan bir işlem için onlarca milisaniyeye varır.
Bu ek yük, bir betik bir arabelleğe her ulaştığında ısırır. Bir QVGA gri tonlamalı çerçeve 76.800 pikseldir; 100 Hz’de bir ivmeölçer saniyede yüz adet üç eksenli örnek sunar; bir mikrofon her 64 ms’de bir 1024 örneklik bir arabelleği doldurur. Bunların herhangi biri üzerindeki saf Python for döngüsü, birkaç mikrosaniye sürmesi gereken bir işi onlarca milisaniye süren bir işe dönüştürür – ve görüntü boyutunda bir arabellekte yaklaşık on kat daha uzun.
6.1.1. Kütüphane fonksiyonları döngülerden daha hızlıdır¶
Çözüm, işlemi elemanları üzerinde bir Python döngüsü yerine, tüm arabellek üzerinde tek bir fonksiyon çağrısı olarak ifade etmektir. numpy tam olarak budur: her işlemin, arabelleği baştan sona bir kez dolaşan, halihazırda optimize edilmiş bir fonksiyon olduğu bir dizi matematiği kütüphanesi. np.multiply(samples, cal), samples‘ın her elemanını cal ile tek bir çağrı içinde çarpar – döngünün yaptığı aynı aritmetik, ancak yineleme başına yorumlayıcı maliyeti olmadan. Bir Python döngüsü olarak onlarca milisaniye süren aynı 1000 elemanlı çarpma, bir numpy çağrısı olarak onlarca mikrosaniye sürer.
Bu, numpy‘nin baştan sona sunduğu anlaşmadır: toplam, ortalama, sin, exp, matris çarpımı, sinyal işleme ilkelleri – her biri, tüm bir arabellek üzerinde aynı anda çalışan tek bir kütüphane fonksiyonudur. Karşılığında verinin numpy’nin dizi türünde yaşaması ve işlemin, elemanları teker teker değil, o diziye karşı ifade edilmesi gerekir.
6.1.2. Neden bir liste yetmez¶
Bir Python list yerini tutamaz. Bir liste herhangi bir nesne karışımını tutabilir – tamsayılar, float’lar, dizgeler, başka listeler – ve onu okuyan bir kütüphane fonksiyonunun, herhangi bir aritmetik gerçekleşmeden önce her yuvaya bakıp içinde ne olduğunu öğrenmesi ve değeri çıkarması gerekir. Bu yuva başına ek yük, tam olarak Python döngüsünün ödediği maliyettir. Listeler, hızlı dizi matematiği için yanlış seçenektir.
6.1.3. Neden bytearray de yeterli değildir¶
Bir bytearray doğru biçimdir – tek bir türlü arabellek, eleman başına bir bayt, hepsi tek bir bitişik blokta. Çoğu bayt yönelimli çevre birimi API’sinin geri verdiği şeydir. Eksik olan şey matematiktir. bytearray * 2, her değeri ikiye katlamak yerine arabelleği tekrarlar ve eleman eleman bytearray + bytearray için makul bir anlam yoktur.
Türlü bir arabelleği eleman bazlı matematikle birleştiren veri yapısı ndarray‘dir. Kutunun içinde ne olduğu ve her alanın hızlı yol davranışını nasıl şekillendirdiği, bölümün geri kalanının üzerinde durduğu temellerdir.