2010-07-12 7 views
15

Non capisco cosa rende la moltiplicazione della matrice in C# /. NET (e anche Java) così lenta.Perché la moltiplicazione della matrice in .NET è così lenta?

Date un'occhiata a questo punto di riferimento ( source): Cercando di trovare un punto di riferimento aggiornato.

Java vs C# vs C++ breakdown http://img411.imageshack.us/img411/9324/perf.gif

intero e doppia performance C# s 'è dannatamente vicino al C++ compilato con MSVC++. 87% più veloce per il doppio e 99% più veloce per i numeri interi a 32 bit. Abbastanza dannatamente bene, direi. Ma poi guarda la moltiplicazione della matrice. Il divario si allarga a C# di circa il 19% più velocemente. Questa è una discrepanza piuttosto grande che non capisco. La moltiplicazione della matrice è solo un mucchio di matematica semplice. Come sta diventando così lento? Non dovrebbe essere approssimativamente veloce come un numero equivalente di semplici operazioni in virgola mobile o intero?

Questo è particolarmente un problema con i giochi e con XNA, dove le prestazioni di matrice e vettori sono fondamentali per cose come i motori fisici. Qualche tempo fa, Mono ha aggiunto il supporto per le istruzioni SIMD attraverso alcune classi di vettori e matrici. Chiude il gap e rende Mono più veloce del C++ scritto a mano, sebbene non veloce come il C++ con SIMD. (source)

Matrix multiplication comparison http://img237.imageshack.us/img237/2788/resultse.png

cosa sta succedendo qui?

Modifica: Guardando più vicino, ho letto male il secondo grafico. C# sembra abbastanza vicino. Il primo benchmark sta solo facendo qualcosa di terribilmente sbagliato? Siamo spiacenti, ho perso il numero di versione sul primo punto di riferimento. L'ho preso come riferimento pratico per "l'algebra lineare C# è lenta" che ho sempre sentito. Proverò a trovarne un altro.

+2

C# Versione + Opzioni: .Net Framework 1.1.4322 Uh ... non c'è una versione più recente? – GalacticJello

+5

* si siede e aspetta di vedere cosa ha da dire JonSkeet sull'argomento * :-) – WestDiscGolf

+0

Il test è stato eseguito con VS 2003. (Si noti anche la versione C++). Da qui l'antica versione di .net. – cHao

risposta

13

Con matrici di grandi dimensioni come questa, la cache della CPU diventa il fattore limitante. Ciò che è iper-importante è come viene memorizzata la matrice. E il codice di riferimento sta confrontando mele e arance. Il codice C++ utilizzava array frastagliati, il codice C# utilizza matrici bidimensionali.

Riscrivere il codice C# per utilizzare matrici frastagliate e raddoppiare la velocità. Riscrivere il codice di moltiplicazione della matrice per evitare che il controllo del limite dell'indice dell'array sembrasse inutile, nessuno userebbe il codice come questo per problemi reali.

+0

Grazie, questo chiarisce le cose. Quindi perché sento sempre (tra le altre ragioni) "XNA è lento perché la moltiplicazione della matrice in C# è lenta"? Non è vero? –

+1

Non so, questa è una richiesta non verificabile da dove mi siedo. I programmatori XNA scrivono spesso il proprio codice di moltiplicazione della matrice? Il codice C/C++ è intransigente quando si parla di velocità e quando si fa esplodere si finisce col raccogliere le schegge dalle orecchie. Se c'è un problema di velocità con un particolare algoritmo in C#, hai sempre C/C++ su cui fare affidamento. –

+1

No, usano la libreria fornita da XNA. –

7

Ben chiaramente l'autore del benchmark non ha compreso la differenza tra gli array frastagliati e multidimensionali in C#. Non è stato davvero un mele-a-mele al confronto. Quando ho cambiato il codice per utilizzare array frastagliati invece di array multidimensionali in modo che funzioni in modo più simile a Java, il codice C# finisce per funzionare due volte più velocemente ... rendendolo più veloce di Java (anche se a malapena e questo è probabilmente statisticamente insignificante). In C# gli array multidimensionali sono più lenti perché c'è un ulteriore lavoro nel trovare lo slot dell'array e perché il controllo dei limiti dell'array non può essere eliminato per loro ... ancora.

Vedere questo question per un'analisi più approfondita del motivo per cui gli array multidimensionali sono più lenti di matrici frastagliate.

Vedere questo blog per ulteriori informazioni sul controllo dei limiti di array. L'articolo in particolare mette in guardia contro l'utilizzo di matrici multidimensionali per la moltiplicazione di matrici.

3

Ecco un punto di riferimento aggiornato trattare con matrice multiplcation (e alcuni benchmark utilizzando la nuova Biblioteca Task Parallel):

Parallel Matrix Multiplication with the Task Parallel Library (TPL)

L'articolo va in modi diversi, e spiega perché gli array multidimensionali sono una scelta sbagliata:

Il modo più semplice matrice moltiplicazione è un array multidimensionale NET con i, j, k ordinare al anse . I problemi sono duplici. Innanzitutto, l'ordinamento i, j.k accede alla memoria in modo febbrile provocando l'immissione di dati in posizioni diverse. . In secondo luogo, utilizza un array multidimensionale . Sì, l'array multidimensionale .NET è conveniente, ma è molto lento.

10

per spiegare l'origine dell'idea che le operazioni di matrice XNA sono lenti:

Prima di tutto c'è il Gotcha-livello principiante: del operator* classe XNA Matrix farà diverse copie. Questo è più lento di quanto ci si potrebbe aspettare dall'equivalente codice C++.

(Naturalmente, se si utilizza Matrix.Multiply(), allora si può passare per riferimento.)

La seconda ragione è che il .NET Compact Framework utilizzato dal XNA su Xbox 360 non ha accesso all'hardware VMX (SIMD) disponibile per i giochi nativi in ​​C++.

Ecco perché continui a sentire che è lento, almeno. Come puoi vedere dai benchmark che hai postato - non è proprio così "lento", quando confronti le mele con le mele.

+1

Questo ha senso. Forse alcuni dei malintesi derivano dall'uso dell'operatore. –