Hallo Zusammen, beim optimieren einer Funktion zum Finden von Minimum und Maximum ist mir aufgefallen, dass -ffast-math die Geschwindigkeit des Codes um ca. Faktor 10 steigert. Der erzeugte Assembler-code wirft jedoch einige fragen auf: http://goo .gl/EhxsaN (Leerzeichen entfernen, sonst spam) so auf den ersten Blick schaut das nach partiellem loop unrolling aus, scheint aber ein bisschen mehr dabei zu sein. Ohne -ffast-math ist Assembler-Code deutlich kürzer aber eben auch um Faktor 10 langsamer. Was für eine anscheinend doch sehr effiziente Optimierung hat hier zugeschlagen? Der mit -ffast-math erzeugte code schafft es dann auch die Speicherbandbreite der CPU vollständig auszulasten. Lukas
Nutzt er denn bei der Variante ohne fast-math auch AVX, wie bei dieser?
Rolf M. schrieb: > Nutzt er denn bei der Variante ohne fast-math auch AVX, wie bei dieser? Jep, kannste bei dem angegebenen Link einfach ausprobieren.
Lukas K. schrieb: > Jep, kannste bei dem angegebenen Link einfach ausprobieren. Sicher nicht. Erste Internet-Grundregel: du sollst nicht auf dubiose Links klicken. Oliver
Lukas K. schrieb: > Was für eine > anscheinend doch sehr effiziente Optimierung hat hier zugeschlagen? An GCC wird seit fast 30 Jahren gearbeitet. Man muss davon ausgehen, dass nicht mal die GCC-Maintainer über jedes Detail Bescheid wissen. Bei solchen Details ist die einzige Dokumentation häufig der Source-Code. https://gcc.gnu.org/wiki/FloatingPointMath enthält ein paar grundlegende Erklärungen, aber nicht die exakten Optimierungs-Algorithmen die verwendet werden. Wenn ich es richtig verstehe sind nicht nur der Compiler, sondern auch die Libraries an fast-math beteiligt. Was bedeutet, man müsste nicht nur im Compiler-Sourcecode, sondern noch in den Libraries nach den Optimierungen suchen. Dann kommt hinzu, dass alle Optimierungen von der Target-Architektur abhängen. Wie du aus dem Link ersehen kannst, hängen die Optimierungen auch noch gegenseitig voneinander ab.
Lukas K. schrieb: > Was für eine > anscheinend doch sehr effiziente Optimierung hat hier zugeschlagen? Der Kern bei grossem <n> ist nicht in klassischem Sinn unrolled, sondern über AVX vektorisiert. Langsame Version, 32 Bits am Stück:
1 | .L6: |
2 | vmovss xmm0, DWORD PTR [rax] |
3 | add rax, 4 |
4 | vmaxss xmm2, xmm0, xmm2 |
5 | vminss xmm1, xmm0, xmm1 |
6 | cmp rsi, rax |
7 | jne .L6 |
Schnelle Version: 256 Bits am Stück:
1 | .L9: |
2 | vmovaps ymm2, YMMWORD PTR [r11] |
3 | add eax, 1 |
4 | add r11, 32 |
5 | vmaxps ymm1, ymm1, ymm2 |
6 | vminps ymm0, ymm0, ymm2 |
7 | cmp r9d, eax |
8 | ja .L9 |
:
Bearbeitet durch User
A. K. schrieb: > Lukas K. schrieb: >> Was für eine >> anscheinend doch sehr effiziente Optimierung hat hier zugeschlagen? > > Der Kern bei grossem <n> ist nicht in klassischem Sinn unrolled, sondern > über AVX vektorisiert. > [...] Danke, klingt einleuchtend. Allerdings bleibt die frage, weshalb GCC das erst mit -ffast-math macht, müssen dazu Umformungen gemacht werden, die zu Ungenauigkeiten führen können. Aber schon beeindruckend, was ein moderner Compiler da schafft. Hätte ich in ASM niemals hinbekommen. Oliver S. schrieb: > Lukas K. schrieb: >> Jep, kannste bei dem angegebenen Link einfach ausprobieren. > > Sicher nicht. Erste Internet-Grundregel: du sollst nicht auf dubiose > Links klicken. > > Oliver Der Link zeigt auf http://gcc.godbolt.org/ In der URL selbst ist allerdings noch der gesamte Sourcecode enthalten: http://gcc.godbolt.org/#{%22version%22%3A3%2C%22filterAsm%22%3A{%22labels%22%3Atrue%2C%22directives%22%3Atrue%2C%22commentOnly%22%3Atrue}%2C%22compilers%22%3A[{%22sourcez%22%3A%22G4ewlgJgBAtghgDwIICcVwJ4AoBmAbEOAFwCooEAaKAVwDsBnMAc1oFNoxaipar9DuJEPD4FiUITDABKKAG8AUFCgBIfuKlQAvOQDaABgC6AbiVR13eNr1HTy5ThAooWTtzDX9xqB4A8PbzAAaiDZRXsInxwXBF0wQwA%2BeFl4LVj4u0iomLjDXykUsDTczOUAXzNJOGt4TMkPHSlTMqAAA%3D%3D%22%2C%22compiler%22%3A%22g520%22%2C%22options%22%3A%22-O3%20-march%3Dbroadwell%20-ffast-math%22}]} (war doch kürzer als erwartet)
Lukas K. schrieb: > Aber schon beeindruckend, was ein > moderner Compiler da schafft. Hätte ich in ASM niemals hinbekommen. Wird einfacher wenn du davon ausgehen darfst, dass die Daten auf 32 Bytes aligned sind und n durch 8 teilbar ist. Ein erheblicher Teil des Codes hat damit zu tun, dass dies hier nicht garantiert ist. Mit AVX-512 ändert sich das dann freilich wieder. Sowas überlässt man auch deshalb lieber dem Compiler.
:
Bearbeitet durch User
Lukas K. schrieb: > erst mit -ffast-math macht, müssen dazu Umformungen gemacht werden, die > zu Ungenauigkeiten führen können. Möglicherweise ist das Schema dieser Vektorisierung nicht speziell an die Eigenschaften von min/max angepasst, sondern wird auch auf andere Vektoroperationen analoger Bauweise angewandt, bei denen das exakte Ergebnis von der Reihenfolge der Rechnungen abhängt, wie etwa bei einer Summe.
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.