4.19. Bellek havuzları

Bir çerçeve arabelleği (frame buffer) havuzunda üç tam çözünürlüklü çerçeve tutan, bunun yanında ayrı bir önizleme arabelleği çalıştıran ve hâlâ bir Python betiği ile nesnelerine yer kalan bir kamera, MCU üzerindeki tek bir RAM bloğunun sağlayabileceğinden çok daha fazla belleği aynı anda idare ediyordur. MicroPython her şeyi, MCU’nun sağladığı birkaç farklı bellek türüne yayarak ve her tahsis türünü gerçekten ihtiyaç duyduğu bellek türüne yönlendirerek sığdırır.

4.19.1. Bellek türleri

Modern bir OpenMV Cam MCU’su dört farklı bellek türü sunar. İlki uygulamaya görünmezdir; diğer üçü ise tahsislerin gelebileceği havuzlardır.

  • CPU’nun veri önbelleği – CPU ile RAM’in geri kalanı arasında yer alan küçük ve çok hızlı bir bellek bölgesi. CPU ana bellekten bir değer okuduğunda veya yazdığında, önbellek otomatik olarak bir kopyasını saklar; böylece aynı veriye yapılan tekrarlı erişimler önbellekte kalır ve hiçbir zaman daha yavaş belleğe gitmenin bedelini ödemez. Önbellek tahsislerin geldiği bir havuz değildir. Uygulamaya karşı saydamdır – yalnızca, bir çalışma kümesi içine sığmayı kestiği noktaya kadar, RAM’in geri kalanını ham gecikmesinin gösterdiğinden pratikte daha hızlı hissettirir.

  • Sıkıca bağlı işlemci belleği – arada hiçbir veri yolu olmadan doğrudan CPU’ya bağlanmış küçük bir RAM bloğu. Tek çevrimde erişim, hiç ıskalamaz, hiç beklemez. Gerçekten mümkün olan en hızlı belleğe ihtiyaç duyan – her gecikme çevriminin önem taşıdığı – tahsisler bu havuzdan gelir.

  • Hızlı yonga üstü bellek – MCU paketine gömülü, birkaç yüz kilobayttan yaklaşık bir megabayta kadar RAM. Düşük gecikme, yüksek bant genişliği, ancak boyutu sınırlı. MicroPython yığını (heap) burada bulunur, böylece Python nesne erişimleri hızlı kalır; CPU’nun sık dokunduğu daha küçük çalışma arabellekleri de bu havuzu paylaşır.

  • Daha yavaş toplu bellek – MCU’yu harici bir bellek yongasıyla eşleştiren kartlarda, harici veri yolu üzerinden erişilen onlarca megabaytlık yonga dışı RAM. Çok daha büyük, ancak her erişim yonga üstü bellekten daha uzun sürer; veri önbelleği, içine sığdırabildiği çalışma kümeleri için bu maliyetin büyük kısmını gizler ve fark, önbelleğe sığamayacak kadar büyük veriler üzerinde gezinen işlemlerde ortaya çıkar. Büyük olması gereken ve CPU’nun daha düşük hızda tolere edebileceği tahsisler için kullanılır – en önemlisi de çerçeve arabelleği (frame buffer) havuzu.

Bu aileye ait kartlar bir yelpazeye yayılır: bazılarında yalnızca yonga üstü RAM bulunur; bazıları yonga üstü RAM’i çok daha büyük bir harici blokla eşleştirir. Tahsis edilebilir üç türün her biri bir bellek havuzu – tahsislerin geldiği bir parça – olarak ele alınır ve etiketlenir; böylece her istek gerçekten ihtiyaç duyduğu bellek türünü isteyebilir.

4.19.2. Birincil çerçeve arabelleği

snapshot() çağrısını destekleyen çerçeve arabelleği (frame buffer) hızlı bellek istemez. Yeterince bellek ister – fazlasını değil. Bu da onu hangi havuz en büyükse oraya koyar; dolayısıyla hem yonga üstü hem de harici belleği olan bir kartta çerçeve arabelleği harici bloğa yerleşir.

Tam çözünürlüklü, üç kat arabellekli bir çerçeve arabelleği, çoğu parçada hızlı yonga üstü havuza sığmayacak kadar büyüktür; onu tutabilecek tek havuz daha büyük olandır. Uygulama görüntüyü işlerken CPU’nun veri önbelleği erişim başına maliyetin büyük kısmını gizler ve çerçeve arabelleğini sensörden dolduran DMA motoru her durumda sensörün veri hızına ayak uydurur.

Çerçeve arabelleğinin aldığı tam boyut, geçerli pixformat(), framesize() ve framebuffers() sayısından belirlenir; bunlardan herhangi biri her değiştiğinde büyür veya küçülür.

4.19.3. İkincil sensör çerçeve arabellekleri

İkinci bir CSI örneği, birincilin kullandığı havuzdan tahsis edilen kendi çerçeve arabelleğine sahip olur. Havuz paylaşılır; arabellekler bağımsızdır. İkincilin ayak izi normalde birincilinkinden çok daha küçüktür, çünkü ikincil sensörler daha düşük çözünürlüklerde çalışır; bu nedenle ikinci çerçeve arabelleğinin aldığı ek bellek, birincilinkinin küçük bir kesridir.

4.19.4. Akış çerçeve arabelleği

görüntü önizleme arabelleği istisnadır. Çalışma zamanında havuzların hiçbirinden tahsis edilmez; derleme zamanında ayrılmış, bilinen bir adrese ve bilinen bir boyuta sahip sabit bir bölgedir. Bu, önizleme yolunu diğer tüm tahsislerin yolundan uzak tutar – bölge önyüklemeden itibaren vardır ve asla yerinden oynamaz.

4.19.5. MicroPython yığını (heap)

Python nesneleri – değişkenler, listeler, sözlükler, sınıf örnekleri, bir snapshot() çağrısının döndürdüğü Image sarmalayıcısı, uygulamanın oluşturduğu her dize ve demet – birden kameranın bellek havuzlarından ayrı olan MicroPython çöp toplamalı yığınında (heap) bulunur. Çöp toplamalı (GC) yığın, MicroPython’ın kendisinin yönettiği bir bellek bölgesidir: Python kodu her nesne oluşturulduğunda buradan örtük olarak tahsis yapar ve MicroPython yığını düzenli aralıklarla tarayarak uygulamanın artık başvurmadığı nesnelerin kapladığı alanı geri kazanır; böylece uygulamanın hiçbir şeyi elle serbest bırakması gerekmez.

Önyüklemede GC yığını için ayrılmış bir bölge bir kenara konur; Python erişiminin hızlı kalması için tipik olarak hızlı yonga üstü belleğe yerleştirilir ve büyük veri yapıları için daha fazla alana ihtiyaç duyan kartlarda daha büyük harici bloğa isteğe bağlı bir taşma sağlanır.

snapshot() tarafından döndürülen Image, GC yığınında bulunan küçük bir sarmalayıcı nesnedir; altta yatan piksel verisi ise kameranın havuzlarından birindeki çerçeve arabelleğinde bulunur. İkisi asla aynı bellek için yarışmaz.

4.19.6. Hepsini bir araya getirmek

Her tahsis türünü doğru havuza yönlendirmek – büyük arabellekleri sığabildikleri daha büyük havuza, gecikmeye duyarlı verileri daha hızlı havuzlara, Python yığınını kendi bölgesine, önizlemeyi ayrılmış yuvasına – toplamda yalnızca birkaç megabayt hızlı belleği olan parçalarda tam çözünürlüklü bir yakalama hattını, bir önizleme kanalını ve önemsiz olmayan bir Python betiğini yan yana çalıştırmayı mümkün kılan şeydir.