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 |
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.
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.
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.