Software > Coding
Kopie Funktion
tuxie:
Hallo,
ich habe hier eine Sauber funktionierende Funktion zum Kopieren von Pixeln, doch diese Läuft sehr unsauber bzw. erzeugt beim Kompilieren keinen Optimalen Code was zur Folge hat das das Kopieren sehr lange dauert. Mit Assembler haben wir diese um das 5 Fache beschleunigen können. Aber das Ziel ist diese in C zu lassen da sie an mehreren stellen Verwendung findet.
Gegebenheiten !
Unbestimmte Anzahl an Zeilen
Unbestimmte Anzahl an Pixeln pro Zeile
32Bit Kopieren ist möglich. (Pointer recast? )
Wie würdet ihr die Schleifen so optimal wie möglich aussehen lassen ?
Wie könnte man mehrere Pixel pro Schleifendurchlauf kopieren.
Sollte man anstatt auf den Pointer der Adresse zuzugreifen lieber auf einen direkten wert zugreifen ?
Ich wäre für Ideen dankbar!
Hier ist der Ausgangscode !
https://franke.ms/cex/z/mWH7zF
mfro:
erstmal
--- Code: ----fomit-frame-pointer -O2
--- Ende Code ---
bei den Compiler-Optionen ergänzen. Sonst optimiert gcc 1. nichts und führt 2. unnötigerweise frame-pointer mit.
Auf den ersten Blick scheinen die Schleifenzähler in den Schleifen nicht genutzt zu werden. Du kannst also die Schleifen statt von h bzw w - 1 bis 0 von h bzw. w -2 bis -1 laufen lassen, ohne dass sich sonst etwas ändert.
Mit etwas Glückt verwendet gcc dann ein dbra.
Dein Compiler explorer verwendet gcc 2.95. Der ist mittlerweile etwa 20 Jahre alt und bezüglich Optimierung - vorsichtig ausgedrückt - nicht auf der Höhe der Zeit.
Tu' dir einen Gefallen und nimm' was neueres. 4.6.4 ist zwar auch nicht aktuell, aber diesbezüglich deutlich besser.
Thorsten Otto:
Schau mal ins Popup, da kann man auch gcc 6.5 und gcc 8.2 auswählen ;)
@tuxie: auch wenns nicht deine Seite ist, hast du zufällig ne Ahnung wie man ne eigene *public* Instance von compiler-explorer aufsetzt?
tuxie:
Hallo Ihr beiden,
also generell geht es mir nicht um die Compiler Optimierung, die steht ja dann eh im makefile und ist bereits auf -O2 -fomit..... gesetzt. Mir geht es wirklich um die Optimierung des Ablaufes um so viele Daten wie moeglich in kürzester Zeit zu kopieren. Hier in dem fall haben wir zwei schleifen, einmal die schleife für die Zeilen und eine fuer die Pixel pro Zeile. Der Gedanke war das man mehrere Pixel pro durchlauf kopiert um so wenig wie moeglich Schleifendurchlaeufe zu haben.
Compiler habe ich im übrigen den 4.6.4 von Vincent im Einsatz. Will aber jetzt mal schauen das ich auf den 8er gehen kann.
Zum Code, eins habe ich schon rausgefunden, ich muss die beiden Zähler ints zu short int machen (reicht ja aus) dann feuert er auch dbra aus da dbra nur short kann laut aussagen von Gunnar alias BigGun
Im nächsten war die Idee eine Abfrage zu machen wie oft eine gewisse Zahl in die Pixel passt und demnach 3 oder 4 Routinen zu bauen er 1 2 3 4 pixel jeweils auf einmal kopiert.
@Thorsten Otto
schau mal hier
https://github.com/mattgodbolt/compiler-explorer
Thorsten Otto:
--- Zitat ---also generell geht es mir nicht um die Compiler Optimierung, die steht ja dann eh im makefile und ist bereits auf -O2 -fomit.
--- Ende Zitat ---
Das ist schon klar, nur solltest du dann nach Möglichkeit auch für den compiler-explorer einen link posten wo das gesetzt ist (und ein entsprechender compiler benutzt wird), ansonsten kann man schlecht beurteilen ob eine Änderung wirklich besseren code bring. Ganz ohne Optimierung ist der erzeugte code ziemlich grottig.
--- Zitat ---Zum Code, eins habe ich schon rausgefunden, ich muss die beiden Zähler ints zu short int machen (reicht ja aus)
--- Ende Zitat ---
--- Zitat ---ich muss die beiden Zähler ints zu short int machen (reicht ja aus) dann feuert er auch dbra aus
--- Ende Zitat ---
Nicht zwangsläufig. Insbesondere wenn int nicht = short, ist der erzeugte code dann meistens schlechter als vorher. Ausserdem scheint er es zu bevorzugen, schon vor der Schleife das erwartete Ende für eine der Adressen zu berechnen, und dann in der Schleife die Adresse zu vergleichen.
Tests (alle mit -O2 -fomit-frame-pointer -mshort):
--- Code: ---void test(char *dst, char *src, unsigned short n)
{
short i;
for (i = n - 1; i >= 0; i--)
*dst++ = *src++;
}
--- Ende Code ---
Erzeugt mit gcc 4.6.4:
--- Code: ---_test:
move.l 4(%sp),%a0
move.w 12(%sp),%d0
subq.w #1,%d0
jmi .L1
move.l 8(%sp),%a1
.L3:
move.b (%a1)+,(%a0)+
subq.w #1,%d0
jpl .L3
.L1:
rts
--- Ende Code ---
Mit gcc 7.3.1:
--- Code: ---_test:
move.l 8(%sp),%a0
move.w 12(%sp),%d0
subq.w #1,%d0
jmi .L1
move.l 4(%sp),%a1
.L3:
move.b (%a0)+,(%a1)+
dbra %d0,.L3
.L1:
rts
--- Ende Code ---
(sieht ganz gut aus). Aber mit gcc 8.3.0:
--- Code: ---_test:
move.l %d2,-(%sp)
move.l 12(%sp),%d2
move.w 16(%sp),%d1
move.w %d1,%d0
subq.w #1,%d0
jmi .L1
move.l 8(%sp),%a1
move.l %d2,%a0
.L3:
move.b (%a0)+,(%a1)+
move.w %a0,%d0
not.w %d0
add.w %d2,%d0
add.w %d1,%d0
jpl .L3
.L1:
move.l (%sp)+,%d2
rts
--- Ende Code ---
Die letzte Version versteh ich irgendwie nicht, da bezieht er irgendwie die Addresse selber mit ein. Da scheint noch was falsch zu laufen, oder zumindest suboptimal.
--- Zitat ---schau mal hier
--- Ende Zitat ---
Ja, kenn ich, hab ich auch schon lokal laufen. Mir ist nur nicht ganz klar wie man den auf 'nem öffentlichen Web-Server zum laufen kriegt, ohne daß er sich mit dem normalen HTTP-Server beisst. Funktioniert möglicherweise nur mit Aber schauen wir mal.
Navigation
[0] Themen-Index
[#] Nächste Seite
Zur normalen Ansicht wechseln