Guten Morgen,
ich hab eine Algorithmus, der ein 640*480px großes Bild debayern [1]
soll.
Die erste Version war in C und erreichte um die 30ms. Nach tagelangem
hinbauen - bin noch Blackfin Anfänger - hab ich eine Assemblerroutine
gebaut, die 18ms benötigt. Die Assemblerroutine verwendet Vektor-Befehle
und berechnet nichts zweimal.
Trotzdem erscheint mir das auf einem 500MHz DSP noch reichlich lahm.
Meine Vermutung ist, dass ich keine Ahnung von der internen 10stufigen
Pipeline-Struktur hab und ich mich daher selbst massiv ausbremse.
Source-Code hab ich leider nicht da, der sieht aber in etwa so aus:
1
r0 = [p0];
2
(r1,r0) = byteunpack r1:r0;
3
r0 = [p0+640];
4
(r3,r2) = byteunpack r1:r0;
5
6
// mittelwert aus r0 und r2, bzw r1 und r3 berechnen
7
r4 = r0 +|+ r2;
8
r5 = r1 +|+ r3;
9
r6 = r4 >> 1;
10
r7 = r5 >> 1;
11
12
// mittelwert aus 4 pixel berechnen
13
r0 = r4 +|+ r5;
14
r0 = r0 >> 1;
15
16
usw ...
Ich glaub, dass ich da viele Datenabhängigkeiten reinkrieg, weil die
Ergebnisse der Berechnungen zu früh gebraucht werden.
Hat jemand Literatur als PDF oder als Buchempfehlung, die auf
Datenkonflikte innerhalb der Blackfin-Pipeline eingeht? Oder
Vorlesungsunterlagen oder irgendwas?
Oder sieht jemand auf den ersten Blick einen grundsätzlichen Fehler?
Es scheint da sooo wenig zu geben ...
Grüße
Thomas
[1]: http://de.wikipedia.org/wiki/Bayer-Sensor
Beispiel oben ist natürlich nicht ganz richtig ... nur mal eben aus der
Erinnerung hingeschrieben ... zB "r6 = r4 >> 1;" sollte "r6 = r4 >> 1
(v);" heißen usw ...
Hi,
Betreffend Pipelining scheint mir nichts 'Boeses' in deinem Code, das
sollte der Blackfin soweit effizient abarbeiten.
Aber ein paar andere Fragen/Bemerkungen
- Laeuft dein Code auch im L1 Prog SRAM? (0xffa0xxxx)
- Wenn die Daten im SDRAM liegen, werden auch da wieder Wartezyklen
fällig
- Cache enabled, und CPLBs entsprechend deiner Bildgroesse / dem
Speicherbereich konfiguriert?
- Falls eh alles unter uClinux laeuft: Da wird dir immer wieder ein
Interrupt die Pipeline versauen. Das Cache macht wieder was wett, aber
wenn Du da optimale Performancekontrolle haben wolltest, muesstest Du
das ganze in einen Kernel-Treiber (ev. sogar Realtime-Treiber) packen.
Habe unter uClinux einen Debayer im Blackfin ('billig', also C) laufen,
duerfte in etwa auch bei 50ms gelegen haben (bei hoeherer Aufloesung).
Das koennte also hinkommen.
Zur Pipeline: Es gab mal irgendwo einige Folien als PDF, auf der die
Pipeline-Struktur lose skizziert war. Aber die ganzen Details gibts
leider nur gegen furchtbar dicke NDAs (soweit ich weiss, und das bei
Intel).
Google mal nach "Blackfin seminar pdf" oder so. Wenn ich's finde, sag
ich Bescheid.
Gruss,
- Strubi
> - Laeuft dein Code auch im L1 Prog SRAM? (0xffa0xxxx)
Ööööh ... Wenn ucLinux den da nicht hingeladen hat, dann nicht. Aber wie
hat man unter ucLinux da Kontroller darüber?
> - Wenn die Daten im SDRAM liegen, werden auch da wieder Wartezyklen> fällig
Ja, die Daten liegen aufgrund der Größe dort. Ich hab mal versucht alle
8 32Bit-Wörter vorab zu laden und in Register zu packen, damit sie
irgendwann sofort verfügbar sind und damit evtl die Latenz beim
Datentransfer verschleiert wird - es ist aber nur noch langsamer
geworden. Scheint recht gut gecached zu sein ...
> - Cache enabled, und CPLBs entsprechend deiner Bildgroesse / dem> Speicherbereich konfiguriert?
Ah ... keine Ahnung. Was ist ein CPLB? Cache funktioniert aber
prinzipiell schon, weil ich hab einen Speicherbenchmark ausprobiert, den
ich irgendwo gefunden habe und erreichte das praktische Maximum, wenn
Cache aktiviert ist.
Okay, werd mal nach den PDFs gurgeln ...
Danke!
Grüße
Thomas
Hi Thomas,
Vergiss CPLB in dem Fall :-) uClinux macht das alles (meist) richtig.
Handelt sich dabei um die Cache-Konfiguration, man kann gewisse
Speicherbereiche (Pages) unterschiedlich cachen lassen.
Ich denke, viel mehr Performance holst Du nicht mehr raus. Ich hab die
Rechnung zur Anzahl Zyklen noch nicht gemacht, waere mal interessant zu
sehen, was uClinux fuer so eine grosse 'Schleife' noch fuer Overhead
einfuehrt.
Viel Erfolg,
- Strubi
Thomas: Hab das PDF gefunden, ist etwas in die Jahre gekommen (2004).
Lass mir doch mal deine Adresse zukommen (z.b. via
http://www.section5.ch/order.php) dann schicke ich Dir das Ding. Steht
allerdings sehr wenig zur Pfeifenlinie drin..
Gruss,
- Strubi
Ok, bloede Anmerkung und sicherlich schon bedacht, aber gerade bei
Schleifen mit wenigen Befehlen wird sich der zero-overhead-Hardware-loop
eignen, das ganze noch zu beschleunigen. Wenngleich nicht weiter
recherchiert koennte ich mir naemlich vorstellen, dass der Blackfin
sonst bei einem Sprung immer die komplette Pipeline verwirft, mit
diesem, weil der Sprung vorhersehbar ist, aber nicht. Sollte ich mit der
Hoffnung falsch liegen, bitte ich um Korrektur.
Gruss, Joern
Hi Joern,
Nur noch ne Anmerkung:
LSETUP-Hardware-Schleifen sollten ansich vom Compiler ausgegeben werden,
wenn keine Abbruch-Bedingungen existieren. Sonst gibt's auch die (BP)
('branch prediction') Option fuer vorhersehbare Spruenge. Allerdings
muss man dabei teils die Spruenge an ganz paradoxen Orten plazieren,
damit die Berechnung wirklich effizient wird, z.B., so spaet wie
moeglich (die Pipeline hat 10 stages). In C erschiene das als
ineffizienter Overhead, aber fuer die Pipeline ist es so optimaler.
Da das Know-How des Blackfin ja von Intel kommt, kann man sich das
Verhalten und die Coding-Techniken bestimmt von den Pentium-Prozessoren
abgucken..
Gast: Hast Du schon weiteres rausoptimieren koennen? Wuerde mich noch
interessieren..
Gruss,
- Strubi