Forum: PC-Programmierung GCC-Optimierungen bei -ffast-math


von Lukas K. (carrotindustries)


Lesenswert?

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

von Rolf M. (rmagnus)


Lesenswert?

Nutzt er denn bei der Variante ohne fast-math auch AVX, wie bei dieser?

von Lukas K. (carrotindustries)


Lesenswert?

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.

von Oliver S. (oliverso)


Lesenswert?

Lukas K. schrieb:
> Jep, kannste bei dem angegebenen Link einfach ausprobieren.

Sicher nicht. Erste Internet-Grundregel: du sollst nicht auf dubiose 
Links klicken.

Oliver

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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

von Lukas K. (carrotindustries)


Lesenswert?

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)

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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
Noch kein Account? Hier anmelden.