Domanda

Nella mia esperienza, NET è da 2 a 3 volte più lento di codice nativo. (Ho implementato L-BFGS per l'ottimizzazione multivariata).

Ho tracciato gli annunci su StackOverflow per http://www.centerspace.net/products/

la velocità è veramente sorprendente, la velocità è vicino a codice nativo. Come possono farlo? Hanno detto che:

  

Q. È NMath .NET "pura"?

     

A. La risposta dipende un po 'dalla vostra definizione di ".NET puro". NMath è scritto in C #, oltre a un piccolo strato di Managed C ++. Per migliorare le prestazioni delle operazioni di base di algebra lineare, tuttavia, NMath fa affidamento sul nativo di Intel Math Kernel Library (incluso con NMath). Ma non ci sono componenti COM, nessuna DLL - solo assembly .NET. Inoltre, tutta la memoria allocata nello strato C ++ gestito e utilizzato dal codice nativo è allocato dalla memoria dinamica.

Qualcuno può spiegare di più a me?

È stato utile?

Soluzione

Il punto su C ++ / CLI è corretta. Per completare il quadro, a soli due punti interessanti addizionali:

  • NET gestione della memoria (garbage collector) ovviamente non è il problema qui, come NMath dipende ancora su di esso

  • Il vantaggio di prestazioni è effettivamente fornito da Intel MKL, che offre implementazioni estremamente ottimizzate per vari CPU. Dal mio punto di vista, questo è il punto cruciale. Utilizzando straight-forward, il codice naiv C / C ++ abituato necessariamente ti danno prestazioni superiori su C # /. NET, a volte è anche peggio. Tuttavia C ++ / CLI permette di sfruttare tutte le opzioni di ottimizzazione "sporche".

Altri suggerimenti

  

Come possono farlo?

Come la maggior parte delle librerie numeriche per .NET, NMath è poco più di un wrapper su un processore Intel MKL incorporato nel assembly .NET, probabilmente per il collegamento con C ++ / CLI per creare un assemblea mista . Probabilmente avete appena benchmark quei bit che non sono in realtà scritte in .NET.

L'articoli F # .NET Journal numeriche Biblioteche: funzioni speciali, interpolazione e casuali numeri (16 marzo 2008) e librerie numeriche: algebra lineare e metodi spettrali (16 aprile 2008) ha testato un po 'di funzionalità e NMath era in realtà la più lenta di tutte le librerie commerciali. La loro PRNG è stato più lento di tutti gli altri e il 50% più lento rispetto alla biblioteca Math.NET libera, alcune funzionalità di base mancava (per esempio la capacità di calcolare Gamma(-0.5)) e altre funzionalità di base (i Gamma-correlate funzioni Ci hanno fornito) era rotto. Sia Estrema Ottimizzazione e Bluebit battere NMath presso il punto di riferimento eigensolver. NMath non ha nemmeno fornire una trasformata di Fourier al momento.

Ancora più sorprendente, le differenze di prestazioni sono stati a volte enormi. Il più costoso biblioteca numerica commerciale abbiamo testato (IMSL) è stato di oltre 500 × più lento rispetto alla libreria di FFTW gratuitamente presso il punto di riferimento FFT e non delle librerie fatto uso di più core, al momento.

In realtà, è proprio la scarsa qualità di queste librerie che ci ha incoraggiato a commercializzare il nostro rel="noreferrer"> biblioteca (che è 100% puro codice F #).

Io sono uno dei principali sviluppatori di ILNumerics . Quindi io sono di parte, ovviamente;) ma siamo più divulgate sulle nostre interni, in modo da darò alcuni spunti i nostri di velocità 'segreti'.

Tutto dipende da come le risorse di sistema sono utilizzate! Se siete in procinto velocità pura e la necessità di gestire grandi array, si farà in modo di (in ordine di importanza, più importante prima)

  1. Gestisci la tua memoria in modo appropriato! 'Naive' gestione della memoria porterà a cattive prestazioni, dato che sottolinea l'GC male, provoca la frammentazione della memoria e degrada la frazione memoria (quindi le prestazioni cache). In un ambiente raccolto immondizia come NET, questo si riduce a impedendogli di frequenti allocazioni di memoria. In ILNumerics, abbiamo implementato un pool di memoria ad alte prestazioni, al fine di raggiungere un 'questo obiettivo (e lo smaltimento deterministica di array temporanei per ottenere una sintassi piacevole, confortevole, senza la semantica funzione maldestri).

  2. sfruttare il parallelismo! Questo si rivolge sia: a livello di thread parallelismo e livello di dati parallelismo. nuclei multipli sono utilizzati mediante filettatura calcolo parti intensivo del calcolo. Su X86 / X64 CPU SIMD extensions / multimediali come SSE.XX e AVX consentire un piccolo ma efficace vettorizzazione. Essi non sono indirizzabili direttamente dai linguaggi attuali .NET. E questa è l'unica ragione, perché MKL può è ancora più veloce di codice di 'puro' NET. (Ma le soluzioni sono già in aumento.)

  3. Per raggiungere un ' la velocità di lingue altamente ottimizzati come FORTRAN e C ++, le stesse ottimizzazioni devono ottenere applicati sulla codice come fatto per loro. C # offre la possibilità non farlo.

Nota, queste precauzioni dovrebbero essere seguiti in questo ordine! Non ha senso preoccuparsi di estensioni SSE o addirittura la rimozione di controllo legato, se il collo di bottiglia è la larghezza di banda della memoria e il processore (s) trascorrono la maggior parte del tempo di attesa per i nuovi dati. Inoltre, per molte operazioni semplici che non ha nemmeno paga di investire enormi sforzi per archieve all'ultimo piccola scala fino al massimo delle prestazioni! Si consideri l'esempio comune della funzione LAPACK DAXPY. Aggiunge gli elementi di un vettore X corrispondente elemento di un altro vettore Y. Se questo viene fatto per la prima volta, tutta la memoria per X e Y dovrà ottenere recuperata dalla memoria principale. C'è poco o nulla si può fare al riguardo. E la memoria è il collo di bottiglia! Quindi, indipendentemente se l'aggiunta alla fine è fatto nel modo ingenuo in C #

for (int i = 0; i < C.Length; i++) {
    C[i] = X[i] + Y[i]; 
}

o fatto utilizzando strategie di vettorializzazione - si dovrà attendere per la memoria!

Lo so, questa risposta non fa in qualche modo 'sopra le risposte' la questione, dal momento che la maggior parte di queste strategie non sono attualmente utilizzati dal prodotto menzionato (ancora?). Seguendo thoses punti, si potrebbe finalmente finire con prestazioni molto meglio di ogni implementazione ingenuo in una lingua 'nativo'.

Se siete interessati, si poteva rivelare l'implementazione di L-BFGS? Sarò felice di convertirlo in ILNumerics e inviare i risultati del confronto e ne sono certo, altre librerie elencate qui vorrebbero seguire. (?)

ho postato su un blog articolo affrontare questa domanda .

La chiave è C ++ / CLI . Esso consente di compilare il codice C ++ in un assembly gestito .NET.

Oggi è standard del settore per rendere misti librerie .NET / native, al fine di prendere i vantaggi di entrambe le piattaforme per l'ottimizzazione delle prestazioni. Non solo NMath, molte biblioteche commerciali e gratuite con interfaccia .net lavorare in questo modo. Per esempio: Math.NET numerici, dnAnalytics , Primissimo Optimization, FinMath e molti altri. L'integrazione con MKL è estremamente popolare per le librerie numeriche .net, e la maggior parte di loro usano solo Managed montaggio C ++ come un livello intermedio. Ma questa soluzione ha un certo numero di svantaggi:

  1. Intel MKL è un software proprietario ed è un po 'costoso. Ma alcune librerie come dnAnalytics fornisce una sostituzione gratuita di funzionalità MKL con il codice di .net puro. Fuori rotta, che è molto più lento, ma è gratuito e perfettamente funzionante.

  2. Si riduce la compatibilità è necessario avere pesanti ++ gestito DLL del kernel C sia per la modalità 32bit e 64bit.

  3. Gestito alle chiamate nativa necessità di eseguire il marshalling che rallentano le prestazioni di veloci chiamati più frequentemente operazioni come Gamma o normalcdf.

Ultimi due problemi risolti in libreria RTMath FinMath. Io non so davvero come abbiano fatto, ma forniscono singola DLL .net puro che ha compilato per qualsiasi piattaforma CPU e supporta 32bit e 64bit. Inoltre non ho visto alcuna riduzione delle prestazioni nei confronti MKL quando ho bisogno di chiamare normalcdf miliardi di volte.

Dato che il (nativo) Intel MKL sta facendo la matematica, si sta effettivamente non facendo due conti in codice gestito. Si sta semplicemente utilizzando il gestore di memoria da Net, quindi i risultati sono facilmente utilizzati da NET.

Ho imparato il commento di più forma @Darin Dimitrov per la sua risposta e commento di @Trevor Misfeldt a @ commento di Darin. Quindi la pubblicazione come una risposta, per i lettori futuri.

NMath utilizza P / Invoke o C ++ / CLI per chiamare Intel Math Kernel Library funzioni native che è dove i calcoli più intensi sono fatto e che è per questo che è così veloce.

Il tempo è trascorso in metodi di decomposizione all'interno di Intel MKL . Riproduzione vietata dei dati è obbligatorio , sia. Così, non è un problema se CLI è veloce o meno. Si tratta di quando l'esecuzione avviene .

Anche @ blog di Paolo è anche una buona lettura. Ecco il sommario.

C # è veloce, allocazione memoria non lo è. Riutilizzare le variabili come rif o fuori parametri , invece di restituire nuove variabili da metodi. Assegnazione di una nuova variabile consuma memoria e rallenta l'esecuzione. @Haymo Kutschbach ha spiegato bene.

Se la precisione non è necessaria, il miglioramento delle prestazioni nel passaggio da doppia a singola precisione è notevole (per non parlare della memoria risparmio per la memorizzazione dei dati).

Per molti calcoli brevi, per chiamare una ++ / routine di CLI C da C #, appuntare tutti i puntatori ai dati allocati nello spazio gestito, e quindi chiamare la libreria Intel è generalmente meglio che usare P / Invoke per chiamare la libreria direttamente da C # , a causa del costo dei marshalling dei dati. Come già detto da @Haymo Kutschbach nei commenti, per i tipi di copiabili tuttavia, alcuna differenza tra C ++ / CLI e C #. Array di tipi copiabili e classi che contengono solo i membri copiabili sono riposte anziché copiati durante marshalling. Fare riferimento https://msdn.microsoft.com/en -us / library / 75dwhxf7 (v = vs.110) aspx per un elenco dei tipi copiabili e non copiabili.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top