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

: Bearbeitet durch User
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.

: Bearbeitet durch User
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.

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