Con GCC 5.3 il codice seguente compield con -O3 -fma
fusi moltiplicano aggiungere e arrotondamento predefinite Modalità
float mul_add(float a, float b, float c) {
return a*b + c;
}
produce il seguente complesso
vfmadd132ss %xmm1, %xmm2, %xmm0
ret
I noticed GCC doing this with -O3
already in GCC 4.8.
Clang 3.7 con -O3 -mfma
produce
vmulss %xmm1, %xmm0, %xmm0
vaddss %xmm2, %xmm0, %xmm0
retq
ma Clang 3.7 con -Ofast -mfma
produce lo stesso codice di GCC con -O3 fast
.
Mi sorprende che GCC fa con -O3
perché da this answer dice
Il compilatore non è consentito di fondere un separato aggiuntivo e moltiplicare a meno che non si consente per un modello in virgola mobile rilassato.
Questo perché un FMA ha un solo arrotondamento, mentre un ADD + MUL ne ha due. Quindi il compilatore violerà il comportamento in virgola mobile IEEE mediante fusione.
Tuttavia, da this link dice
Indipendentemente dal valore di FLT_EVAL_METHOD, qualsiasi espressione in virgola mobile può essere contratto, cioè, calcolata come se i risultati intermedi hanno portata e precisione infinita.
Quindi ora sono confuso e preoccupato.
- GCC è giustificato nell'uso di FMA con
-O3
? - Il fusing viola il comportamento in virgola mobile IEEE?
- Se la fusione viola il punto di virgola mobile IEEE e poiché GCC returns
__STDC_IEC_559__
non è una contraddizione?
Poiché FMA can be emulated in software sembra esserci dovrebbero essere due interruttori compilatore per FMA: uno a dire al compilatore di utilizzare FMA nei calcoli e uno a dire al compilatore che l'hardware ha FMA.
apprently questo può essere controllato con l'opzione -ffp-contract
. Con GCC il valore predefinito è -ffp-contract=fast
e con Clang non lo è. Altre opzioni come -ffp-contract=on
e -ffp-contract=off
non producono l'istruzione FMA.
Ad esempio Clang 3.7 con -O3 -mfma -ffp-contract=fast
produce vfmadd132ss
.
ho controllato alcune permutazioni di #pragma STDC FP_CONTRACT
set per ON
e OFF
con -ffp-contract
set per on
, off
e fast
.In tutti i casi ho anche utilizzato -O3 -mfma
.
Con GCC la risposta è semplice. #pragma STDC FP_CONTRACT
ON o OFF non fa differenza. Solo gli argomenti -ffp-contract
.
GCC utilizza fma
con
-ffp-contract=fast
(default).
Con Clang utilizza fma
- con
-ffp-contract=fast
. - con
-ffp-contract=on
(predefinito) e#pragma STDC FP_CONTRACT ON
(il valore predefinito èOFF
).
In altre parole con Clang è possibile ottenere fma
con #pragma STDC FP_CONTRACT ON
(dal -ffp-contract=on
è l'impostazione predefinita) o con -ffp-contract=fast
. -ffast-math
(e quindi -Ofast
) impostato -ffp-contract=fast
.
Ho esaminato MSVC e ICC.
Con MSVC utilizza l'istruzione fma con /O2 /arch:AVX2 /fp:fast
. Con MSVC /fp:precise
è l'impostazione predefinita.
Con ICC utilizza fma con -O3 -march=core-avx2
(è sufficiente -O1
). Questo perché di default ICC usa -fp-model fast
. Ma ICC usa fma anche con -fp-model precise
. Per disabilitare fma con ICC utilizzare -fp-model strict
o -no-fma
.
Quindi, per impostazione predefinita, GCC e ICC utilizzano fma quando fma è abilitato (con -mfma
per GCC/Clang o -march=core-avx2
con ICC) ma Clang e MSVC no.
Potrebbe essere un errore del compilatore. Considera di segnalarlo. – fuz
Sono abbastanza sicuro di quello che gcc sta facendo è ok. Dopo aver letto il documento FLT_EVAL_METHOD sulla contrazione delle espressioni FP, sono sorpreso che 'clang' * non lo faccia *. Non sto postando questo come una risposta, dal momento che non si basa su alcuna documentazione di standard reali, solo la mia comprensione di come * I * penso che le cose dovrebbero funzionare/dovrebbero essere state progettate, dato il materiale nella domanda. –
@FUZxxl, pensi che il tag floating point sarebbe più appropriato di ieee-754? (se è così sentitevi liberi di cambiarlo). Sento che dovrei usare anche il tag floating point. –