Perché uno scienziato computazionale dovrebbe implementare la propria versione di std :: complex?


14

Molte delle librerie C ++ più note nella scienza computazionale come Eigen , Trilinos e deal.II usano l'oggetto libreria standard C ++ template header std::complex<>, per rappresentare numeri a virgola mobile complessi.

Nella risposta di Jack Poulson a una domanda sui costruttori predefiniti, sottolinea che ha una sua implementazione di std::complexin Elemental "per una serie di ragioni". Quali sono questi motivi? Quali sono i vantaggi e gli svantaggi di questo approccio?

Risposte:


16

Credo che questa discussione sia venuta più volte nell'elenco PETSc. I miei motivi principali sono:

  1. Lo standard C ++ afferma che std :: complex è definito solo per i tipi di dati float, double e long double. Pertanto non può essere utilizzato per altri tipi di dati, ad esempio quad-precision.

  2. Lo standard non fornisce garanzie sulla stabilità dell'aritmetica complessa.

  3. Lo standard non garantisce che i dati in uno std :: complex siano archiviati come componente reale seguito dal componente immaginario. Questo è fondamentale per le interfacce con librerie esterne, come BLAS e LAPACK. È vero per tutte le principali implementazioni, ma preferirei essere in grado di garantirlo.

  4. Preferisco essere in grado di manipolare direttamente i componenti reali e immaginari. std :: complex rende questo inutilmente difficile.

  5. Vorrei eventualmente avere una versione più generale che richiede solo che il tipo di dati sia un anello invece di richiedere un campo. Ciò include gli interi gaussiani.


6
Il punto 3 è stato affrontato in C ++ 11. 26.4.4 afferma che se zè un'espressione lvalue di tipo cv std::complex<T> poi reinterpret_cast<cv T(&)[2]>(z)e reinterpret_cast<cv T(&)[2]>(z)[0]designa la parte reale di z, e reinterpret_cast<cv T(&)[2]>(z)[1]designa la parte immaginaria z. Vengono anche indirizzate le matrici di numeri complessi.
James Custer,

3
@JamesCuster: Sto per passare a C ++ 11, ma i codici scientifici che vogliono rimanere portatili per architetture semi-esotiche dovranno probabilmente aspettare almeno altri due o tre anni per farlo. Inoltre, C ++ 11 purtroppo risolve solo una parte del problema.
Jack Poulson,

Capisco, lo stavo solo lanciando là fuori nel caso qualcuno guardasse a questa domanda in futuro.
James Custer,

2
Bene, penso che sia un cop-out dire che dovresti aspettare che i compilatori supportino C ++ 11. Il requisito esplicito è stato inserito nel nuovo standard perché tutte le implementazioni esistenti lo supportano già. Non riesco a pensare a un caso in cui non sarebbe sicuro assumere già questo particolare layout nei compilatori / librerie esistenti in quanto non avrebbe semplicemente senso implementare std :: complex in nessun altro modo.
Wolfgang Bangerth,

1
@WolfgangBangerth: è stato più un commento generale sul passaggio a C ++ 11. In entrambi i casi, C ++ 11 non risolve la maggior parte dei problemi con std :: complex.
Jack Poulson il

7

Uso std::complex<>nei miei programmi e devo lottare con i flag del compilatore e la soluzione alternativa per ogni nuovo aggiornamento del compilatore o del compilatore. Proverò a raccontare queste lotte in ordine cronologico:

  1. std::norm|z|2|z|-ffast-math
  2. Il compilatore Intel icc su Linux (o linker) compilato std::argin modo non optato in determinate configurazioni (compatibilità dei collegamenti con una versione gcc specifica). Il problema è riemerso troppo spesso, quindi è std::argstato sostituito da atan2(imag(),real()). Ma era fin troppo facile dimenticare questo quando si scriveva un nuovo codice.
  3. Il tipo std::complexutilizza convenzioni di chiamata diverse (= ABI) rispetto al tipo complesso C99 incorporato e al tipo complesso Fortran incorporato per le versioni gcc più recenti.
  4. Il -ffast-mathflag di compilazione interagisce con la gestione delle eccezioni in virgola mobile in modi imprevisti. Quello che succede è che il compilatore estrae le divisioni dai loop, causando così division by zeroeccezioni in fase di esecuzione. Queste eccezioni non sarebbero mai avvenute all'interno del loop, perché la divisione corrispondente non ha avuto luogo a causa della logica circostante. Quella era davvero pessima, perché era una libreria compilata separatamente dal programma che utilizzava la gestione delle eccezioni in virgola mobile (utilizzando flag di compilazione diversi) e si imbatteva in questi problemi (i team corrispondenti erano seduti in parti opposte del mondo, quindi questo problema ha causato seri problemi). Ciò è stato risolto facendo l'ottimizzazione utilizzata dal compilatore a mano con maggiore cura.
  5. La libreria è diventata parte del programma e non ha più utilizzato il -ffast-mathflag di compilazione. Dopo un aggiornamento a una versione gcc più recente, le prestazioni sono diminuite di un fattore enorme. Non ho ancora studiato in dettaglio questo problema, ma temo che sia correlato all'allegato G C99 . Devo ammettere che sono completamente confuso da questa strana definizione di moltiplicazione per numeri complessi, e sembra addirittura che esistano versioni diverse di questo con affermazioni che le altre versioni sono sbagliate. Spero che il -fcx-limited-rangeflag di compilazione risolva il problema, perché sembra che ci sia un altro problema relativo a -ffast-mathquesta nuova versione di gcc.
  6. Il -ffast-mathflag di compilazione rende il comportamento NaNcompletamente imprevedibile per le versioni più recenti di gcc (anche se isnanè interessato). L'unica soluzione sembra essere quella di evitare qualsiasi occorrenza del NaNprogramma, che vanifica lo scopo dell'esistenza di NaN.

Ora potresti chiedermi se ho intenzione di abbandonare i tipi complessi incorporati e std::complexper questi motivi. Starò con i tipi integrati, purché rimanga con C ++. Nel caso in cui il C ++ dovesse diventare completamente inutilizzabile per l'informatica scientifica, preferirei considerare di passare a un linguaggio che si occupi maggiormente delle questioni relative all'informatica scientifica.


Sembra che le mie paure legate all'allegato G del C99 si siano avverate e -fcx-limited-range è ora un po 'necessario per una velocità di calcolo decente quando si moltiplicano numeri complessi. Almeno questo è quello che ottengo dalla seguente recente storia di guerra: medium.com/@smcallis_71148/…
Thomas Klimpel,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.