2013-03-09 15 views
20

Sono entrato nell'assemblaggio delle funzioni matematiche trascendentali della libreria C con MSVC in modalità fp: strict. Sembrano tutti seguire lo stesso schema, ecco cosa succede per sin.Come determinare se C matematica utilizza SSE2?

Prima c'è una routine di invio da un file chiamato "disp_pentium4.inc". Controlla se è stata impostata la variabile ___use_sse2_mathfcns; in tal caso, chiama __sin_pentium4, altrimenti chiama __sin_default.

__sin_pentium4 (in "sin_pentium4.asm") inizia trasferendo l'argomento da x87 fpu al registro xmm0, esegue il calcolo utilizzando le istruzioni SSE2 e carica nuovamente il risultato in fpu.

__sin_default (in "sin.asm") mantiene la variabile sullo stack x87 e chiama semplicemente fsin.

Quindi, in entrambi i casi, l'operando viene inserito nello stack x87 e riportato su di esso, rendendolo trasparente al chiamante, ma se è stato definito ___use_sse2_mathfcns, l'operazione viene effettivamente eseguita in SSE2 anziché in x87.

Questo comportamento è molto interessante per me perché le funzioni trascendentali x87 sono famose per avere comportamenti leggermente diversi a seconda dell'implementazione, mentre un dato pezzo di codice SSE2 dovrebbe sempre fornire risultati riproducibili.

C'è un modo per determinare per certo, in fase di compilazione o in fase di esecuzione, che verrà utilizzato il percorso del codice SSE2? Non sono abile a scrivere assembly, quindi se ciò comporta la scrittura di un assembly, un esempio di codice sarebbe apprezzato.

+0

In che directory si trovano questi file? –

+0

"f: \ dd \ vctools \ crt_bld \ SELF_X86 \ crt \ prebuild \ tran \ i386 \" - questo è proprio quello che vedo nel disassemblaggio, non ho i file stessi. – Asik

+2

Nah, impossibile, una domanda decente su SO ... Sento un imbarazzante bisogno di andare avanti. –

risposta

7

Ho trovato la risposta attraverso un'attenta analisi di matematica.h. Questo è controllato da un metodo chiamato _set_SSE2_enable.Questo è un simbolo pubblico documentato here:

Attiva o disattiva l'uso di Streaming SIMD Extensions 2 (SSE2) istruzioni in CRT routine matematiche. (Questa funzione non è disponibile sul architetture x64 perché SSE2 è abilitato di default.)

Ciò causa il ___use_sse2_mathfcns bandiera aforementionned da impostare al valore fornito, abilitando o disabilitando l'utilizzo delle routine _pentium4 SSE2.

La documentazione indica che questo riguarda solo alcune funzioni trascendentali, ma guardando allo smontaggio, questo sembra influire su tutti.

Edit: entrare in ogni funzione rivela che sono tutti disponibili in SSE2 ad eccezione dei seguenti:

  • fmod
  • Sinh
  • cosh
  • tanh
  • sqrt

Sqrt è il più grande autore di reato, ma è banale da im plement in SSE2 usando intrinseche. Per gli altri, non esiste una soluzione semplice, ad eccezione forse dell'uso di una libreria di terze parti, ma probabilmente potrei fare a meno.

2

La risposta breve è che non è possibile indicare NEL VOSTRO CODICE per certo ciò che farà la libreria, a meno che non si tratti anche di dettagli specifici dell'implementazione della libreria. Questi renderebbero il codice completamente non portabile - anche due diverse build dello stesso compilatore potrebbero cambiare le parti interne della libreria.

Ovviamente, se la portabilità non è un problema, utilizzare extern <type> ___use_sse2_mathfcns; e verificare se è vero funzionerebbe chiaramente.

Mi aspetto che se il processore ha SSE2 e si utilizza una libreria abbastanza moderna, utilizzerà SSE2 laddove possibile. Ma dire che per certo è una questione diversa.

Se questo è fondamentale per il codice, implementare le proprie funzioni trascendentali e utilizzarle: questo è l'unico modo per garantire lo stesso risultato. In alternativa, utilizzare un codice assembler (o trascendente) in linea appropriato per calcolare i valori selezionati sin, cos, ecc. E confrontarli con le funzioni sin() e cos() fornite dalla libreria.

+0

'extern int ___ use_sse2_mathfcns' mi dà un errore linker. Non so dove sia definito, è solo un nome nel disassemblaggio. – Asik

+0

Prova con uno in meno '_'? –

+0

Anche questo non ha funzionato. – Asik

3

Perché non utilizzare la propria libreria al posto del runtime C? Ciò fornirebbe una garanzia ancora maggiore di coerenza tra i computer (presumibilmente il runtime C è fornito come una DLL e potrebbe cambiare leggermente nel tempo).

Vorrei raccomandare CRlibm. Se stai già bersagliando SSE2 e fino a quando non hai intenzione di cambiare la modalità di arrotondamento della FPU, sei nelle condizioni ideali per usarlo e non troverai un'implementazione più accurata.

+0

In realtà ho bisogno di impostare la precisione e la modalità di arrotondamento della FPU: 53-bit e round-to-nearest. Questo non dovrebbe avere alcuna incidenza sulle routine di CRlibm se sono implementate in SSE2. – Asik

+0

@Dr_Asik La modalità di emulazione dell'istruzione di stack in virgola mobile storica non è perfetta: con l'impostazione per il significato a 53 bit e l'esponente mantiene il suo intervallo esteso completo. In particolare, è difficile evitare i dinieghi a doppio arrotondamento. Tuttavia, CRlibm è progettato per funzionare anche quando si mira a x87 finché è impostato nella modalità di emulazione a cui si fa riferimento: http://lipforge.ens-lyon.fr/www/crlibm/start.html –

+1

+1 per CRLibM. Oltre a garantire una precisione perfetta, di solito è più veloce di GNU LibM e Cephes C. Nel caso in cui si desideri scambiare un po 'di precisione per le prestazioni, dare un'occhiata a FDLibM. –

Problemi correlati