FPGA ile Gerçek Zamanlı Görüntü İşleme
Gerçek zamanlı kelimesi çoğu zaman hızlı anlamında kullanılıyor. Görüntü işlemede karşılığı bu değil. Gerçek zamanlı, her karenin kendine ayrılan süre içinde bitmesi demek. Ortalamada hızlı olup arada bir geciken bir sistem, ortalamada yavaş ama hiç gecikmeyen bir sistemden daha kötüdür.
Ayrı bir yazıda bu zincirin hangi bloklardan oluştuğunu ve blokların sırasının görüntü kalitesini nasıl belirlediğini anlatmıştık. Bu yazı aynı zincire zaman tarafından bakıyor: bloklar yetişiyor mu, gecikme nerede birikiyor ve mimari bu yüzden nasıl şekilleniyor.
Baştan söyleyelim, bu soruların cevabı algoritmalarda değil. Gecikmeyi belirleyen asıl şey, hangi bloğun bir satır, hangisinin bir tam kare beklettiği.
İki farklı kısıt: Verim ve Gecikme
Gerçek zamanlı bir zincirde birbirine karıştırılan iki ölçü var.
- Verim saniyede kaç piksel işleyebildiğinizdir. 1920x1080 60 fps için bu saniyede 124,4 milyon piksel eder ve pazarlığa açık değildir.
- Gecikme ise bir pikselin zincire girmesiyle çıkması arasında geçen süredir. Verimi yakalamak görece kolaydır, paralellikle çözülür. Gecikme ise mimarinin sonucudur; zincir kurulduktan sonra parametreyle ayarlanamaz.
Üstelik gerçek zamanlı bir sistemde kısıt gecikmenin ortalaması değil, en kötü durumudur. Bir kere kaçırılan kare geri gelmez.
Gecikme sınıfları: satır mı, kare mi?
Bu yazının tek cümlelik özeti şu: bir görüntü işleme bloğu ya satır gecikmelidir ya kare gecikmeli, ve bu ayrım sistemin gecikmesini algoritmalardan çok daha fazla belirler.
- Satır gecikmeli bloklar çıkış üretmek için yalnızca birkaç satırlık komşuluğa ihtiyaç duyar. Demosaic, keskinleştirme, uzamsal filtre, renk dönüşümü bu sınıftadır. Pencere yüksekliği kadar satır biriktirir, sonra akmaya başlarlar ve bir daha durmazlar.
- Kare gecikmeli bloklar ise çıkışa başlamadan önce tam bir kare görmek zorundadır. Kare tamponu, zamansal filtre, global histogram, görüntüyü döndüren ya da kare biriktirerek ölçekleyen bloklar buraya girer.
Aradaki fark bir ayar farkı değil, büyüklük mertebesi farkıdır. 1080p60’ta bir satır 15,4 mikrosaniye sürer, beş satırlık bir pencere yaklaşık 77 mikrosaniye eder. Bir tam kare ise 16.670 mikrosaniyedir. Tek bir kare gecikmeli blok, bütün satır gecikmeli blokların toplamından yaklaşık iki yüz kat pahalıdır.
Pratik sonuç şu: zincire kare gecikmeli bir blok eklerken bunun bir mimari karar olduğunu bilin. Gerekiyorsa ekleyin, ama gecikme bütçenizin büyük kısmının oraya gittiğini kabul ederek ekleyin.
Saat frekansı nereden çıkar?
Bir görüntü zincirinin saat frekansı tahminle seçilmez, bölmeyle bulunur.
Saniyedeki piksel sayısını, çevrim başına işlediğiniz piksel sayısına bölünce zincirin gerçek beat hızını elde edersiniz. Çevrim başına tek piksel işliyorsanız 124,4 MHz’lik bir saat gerekir. Dört piksel işliyorsanız 31,1 MHz yeter. 150 MHz’lik bir saat alanında dört pikselle çalışan bir zincir, saatin yaklaşık beşte birini kullanır; kalan pay duraklamalar için tampondur.
Çevrim başına piksel sayısını artırmak veri yolunu genişletir. Her blok artık aynı anda dört pikseli işlemek zorundadır, LUT ve BRAM kullanımı artar, komşuluk pencereleri karmaşıklaşır. Azaltmak ise saati zorlar; 124 MHz’de kapanmayan bir zamanlama 31 MHz’de rahat kapanır.
Zamanlama kapanmıyorsa üç yol vardır. Boru hattına kayıt katmanı eklemek gecikmeyi birkaç çevrim artırır ama bloğun sınıfını değiştirmez, en ucuz çözüm budur. Aracın retiming özelliğini açmak çoğu zaman birkaç yüz pikosaniye kazandırır. Üçüncüsü, çevrim başına piksel sayısını artırıp saati düşürmektir; en etkili yol budur, kaynak maliyeti de en yükseği.
Geri basınç ve FIFO derinliği
Akış zincirinde hiçbir blok her an hazır olmak zorunda değildir. Alıcı hazır olmadığında akış yavaşlar ve bu yavaşlama yukarı doğru yayılır. Bu durumu yönetmek için bloklar arasına FIFO koyarız.
FIFO derinliği tahmin edilmez, hesaplanır: derinlik en az, en uzun duraklama süresi çarpı akış hızı kadar olmalıdır. On mikrosaniyelik bir duraklamayı soğurmak için saniyede 31,1 milyon beat akan bir zincirde 311 beat gerekir; ikinin kuvvetine yuvarlanınca 512.
İşinizi kolaylaştıran bir gerçek var: video akışında satır sonu boşluğu doğal bir tampondur. O aralıkta yeni piksel gelmez ve aşağı akış birikmiş işini bitirebilir. Hesaba oradan başlamak FIFO’ları belirgin şekilde küçültür.
Aşırı derin FIFO da bedava değildir. BRAM harcar ve dolu kaldığı sürece kendi gecikmesini zincire ekler. Doğru derinlik en büyük değil, hesaplanmış olandır.
Ortalama değil, en kötü durum
FPGA’in görüntü işlemede kazandığı yer çoğu zaman ham hız değil, sapmanın yokluğudur.
İşlemci ve GPU tarafında işletim sistemi zamanlayıcısı, önbellek ıskaları, bellek yarışı ve aynı anda çalışan başka süreçler her karenin süresini biraz farklı yapar. Ortalama iyi görünür, dağılımın kuyruğu görünmez. Kaçırılan kareler orada saklanır.
FPGA’de zincir sabit bir devredir. Aynı kare her seferinde aynı sayıda çevrimde işlenir. Veri bağımlı davranan bir blok yoksa ortalama ile en kötü durum arasındaki fark neredeyse sıfırdır.
Kabul kriterinizi de buna göre kurun: ortalama gecikme değil, uzun bir koşumda kaçırılan kare sayısı.
Gecikme nerede toplanır?
Gecikmeyi düşürmeye karar verdiğinizde ilk soru nereye bakılacağıdır ve cevap çoğu kişinin beklediği yer değildir.
Bir video zincirinde gecikmenin büyük bölümü sıkıştırma ve açma adımlarında toplanır. Ağ ve tampon katmanı orta düzeyde bir pay alır. Görüntü işleme bloklarının hesaplama süresi ise, paralel çalıştıkları ve kare başına sabit gecikme ürettikleri için bunların yanında çok küçük kalır.
Bu yüzden görüntü işleme zincirini optimize ederek başlamak genellikle boşa emektir. Önce kodlayıcı ayarlarına, sonra tampon derinliklerine bakın.
Gecikmeyi kartta ölçmek
Tahminle çalışılmaz. Neyse ki gecikmeyi kartta ölçmenin üç pratik yolu var.
- Prob noktaları: Programlanabilir mantık içinde hiç durmayan bir sayaç kurar, zincirin kritik noktalarına o sayacın değerini yakalayan küçük bloklar koyarsınız. Sonuçları AXI4-Lite üzerinden okursunuz. En kesin yöntemdir, saat çevrimi hassasiyetindedir, ama yalnızca programlanabilir mantık içindeki yolu görür.
- Kareye zaman damgası gömmek: Görüntünün içine o anki sayaç değerini yazarsınız ve karşı uçta ekranda okursunuz. Uçtan uca ölçer, kodlayıcı ve ağ dahil her şeyi kapsar.
- Ağ tarafında paket zaman damgalarını yakalamak: Sistem düzeyinde bir resim verir, tampon etkilerini de içerir.
Bir uyarı: bu üç yöntem farklı sınırları ölçer. Verdikleri sayılar tutmuyorsa genellikle üçü de doğrudur, sadece farklı noktalar arasına bakmışlardır. Karşılaştırmadan önce her birinin nereden nereye ölçtüğünü yazın.
Pratik kontrol listesi
- Kare gecikmeli bloklarınızı sayın. Gecikme bütçenizin büyük kısmı orada duruyor, başka hiçbir optimizasyon onunla yarışamaz.
- Saat frekansını bölmeyle bulun. Piksel hızını çevrim başına piksele bölün; çıkan sayı zincirin gerçek kısıtıdır.
- FIFO derinliğini en uzun duraklamadan hesaplayın. Satır sonu boşluğunu hesaba katmak tamponları belirgin küçültür.
- Kabul kriterini en kötü duruma bağlayın. Ortalama gecikme iyi görünürken kaçan kareler dağılımın kuyruğunda saklanır.
- Ölçmeden optimize etmeyin. Suçlu genellikle ilk akla gelen blok değildir.
- İki yöntem farklı sayı veriyorsa ikisi de doğru olabilir. Önce neyi ölçtüklerini karşılaştırın.
Sonuç
Gerçek zamanlı görüntü işleme, algoritmaları hızlandırma işi değil. Zincirin her bloğuna bir zaman sözü verdirme işi.
O söz iki sınıftan birine düşüyor: blok ya birkaç satır bekletir ya bir tam kare. Bu seçim yapıldıktan sonra saat frekansı, FIFO derinlikleri ve kabul kriterleri kendiliğinden şekilleniyor. Yapılmadığında ise sonradan eklenen hiçbir optimizasyon aradaki iki yüz katlık farkı kapatmıyor.
Bizimle İletişime Geçin: info@run-x.com | www.run-x.com