Domanda

Sto scrivendo un programma di elaborazione delle immagini per eseguire l'elaborazione in tempo reale dei fotogrammi video. È in C # usando la libreria Emgu.CV (C #) che avvolge la libreria OpenCV dll (C ++ non gestito). Ora devo scrivere il mio algoritmo speciale e deve essere il più veloce possibile.

Quale sarà un'implementazione più rapida dell'algoritmo?

  1. Scrittura di una funzione 'non sicura' in C #

  2. Aggiunta della funzione alla libreria OpenCV e chiamata tramite Emgu.CV

Suppongo che C # non sicuro sia più lento perché attraversa il compilatore JIT, ma la differenza sarebbe significativa?

Modifica:

Compilato per .NET 3.5 in VS2008

È stato utile?

Soluzione

deve essere il più veloce possibile

Quindi stai ponendo la domanda sbagliata.

Codificalo in assemblatore, con versioni diverse per ogni variante di architettura significativa che supporti.

Usa come guida l'output di un buon compilatore C ++ con ottimizzazione, perché probabilmente conosce alcuni trucchi che non conosci. Ma probabilmente sarai in grado di pensare ad alcuni miglioramenti, perché C ++ non trasmette necessariamente al compilatore tutte le informazioni che potrebbero essere utili per l'ottimizzazione. Ad esempio, C ++ non ha il limite di parole chiave C99. Anche se in quel caso particolare molti compilatori C ++ (incluso MSVC) ora lo supportano, usalo dove possibile.

Ovviamente se vuoi dire, "voglio che sia veloce, ma non nella misura in cui esca da C # o C ++", allora la risposta è diversa ;-)

Mi aspetto che C # almeno si avvicini alle prestazioni di C ++ dall'aspetto simile in molti casi. Presumo ovviamente che il programma funzionerà abbastanza a lungo che il tempo impiegato dalla JIT stessa è irrilevante, ma se stai elaborando molti video allora sembra probabile. Ma mi aspetto anche che ci siano alcune cose che se le fai in C # non sicuro, saranno molto più lente di quelle equivalenti in C ++. Non so cosa siano, perché tutta la mia esperienza di JIT è in Java piuttosto che in CLR. Potrebbero esserci anche cose che sono più lente in C ++, ad esempio se il tuo algoritmo effettua chiamate nel codice C #.

Sfortunatamente l'unico modo per essere sicuri di quanto sia vicino scrivere e testarli, che in qualche modo manca il punto che scrivere la versione C ++ è un mucchio di sforzi extra. Tuttavia, potresti essere in grado di avere un'idea approssimativa hackerando un po 'di codice rapido che approssima l'elaborazione che vuoi fare, senza necessariamente farlo tutto o farlo correttamente. Se il tuo algoritmo eseguirà il loop su tutti i pixel e eseguirà alcune operazioni FP per pixel, quindi la pirateria informatica di un benchmark approssimativo dovrebbe richiedere tutta mezz'ora.

Di solito sconsiglio di iniziare a pensare "questo deve essere il più veloce possibile". I requisiti dovrebbero essere realizzabili e, per definizione, "quanto più X possibile"; è raggiungibile solo al limite. I requisiti dovrebbero anche essere verificabili e "quanto più X possibile" non è verificabile se non si conosce in qualche modo un massimo teorico. Un requisito più amichevole è "questo ha bisogno di elaborare fotogrammi video di tale e tale risoluzione in tempo reale su una tale e tale velocità", o "deve essere più veloce del prodotto del nostro principale concorrente". Se la versione C # lo fa, con un po 'di spazio in più per tenere conto di problemi minori imprevisti nella configurazione dell'utente, quindi lavoro fatto.

Altri suggerimenti

Dipende dall'algoritmo, dall'implementazione, dal compilatore C ++ e dal compilatore JIT. Immagino che nella maggior parte dei casi l'implementazione del C ++ sarà più veloce. Ma questo potrebbe cambiare.

Il compilatore JIT può ottimizzare il codice per la piattaforma su cui è in esecuzione il codice anziché una media per tutte le piattaforme su cui il codice potrebbe essere eseguito come fa il compilatore C ++. Questo è qualcosa in cui le versioni più recenti del compilatore JIT sono sempre più efficaci e possono in alcuni casi dare un vantaggio al codice JITted. Quindi la risposta non è chiara come ci si potrebbe aspettare. Il nuovo compilatore di hotspot Java lo fa molto bene, ad esempio.

Altre situazioni in cui il codice gestito può fare meglio di C ++ è dove è necessario allocare e deallocare molti piccoli oggetti. Il runtime .net prealloca grossi blocchi di memoria che possono essere riutilizzati, quindi non è necessario richiamare il sistema operativo ogni volta che è necessario allocare memoria.

Non sono sicuro che C # non sicuro funzioni molto più velocemente del normale C #. Dovrai provare anche questo.

Se vuoi sapere qual è la soluzione migliore per la tua situazione, dovrai provare entrambi e misurare la differenza. Non credo che ci sarà più di

C # è in genere più lento di C ++. Esistono controlli di runtime nel codice gestito. Questi sono ciò che lo rende gestito, dopo tutto. C ++ non deve verificare se i limiti di un array sono stati superati, ad esempio.

Dalla mia esperienza, l'uso della memoria fissa aiuta molto. C'è un nuovo classe System.IO.UnmanagedMemoryAccessor in .NET 4.0 che potrebbe essere utile in futuro.

Le lingue non hanno una "velocità". Dipende dal compilatore e dal codice. È possibile scrivere codice inefficiente in qualsiasi lingua e un compilatore intelligente genererà un codice quasi ottimale, indipendentemente dalla lingua della fonte.

L'unico fattore davvero inevitabile nelle prestazioni tra C # e C ++ è che le app C # devono fare di più all'avvio (caricare il framework .NET e forse un po 'di codice JIT), quindi, a parità di condizioni, si avvieranno un po' più lentamente. Dopodiché, dipende e non c'è motivo fondamentale per cui una lingua deve essere sempre più veloce di un'altra.

Inoltre non sono a conoscenza di alcun motivo per cui C # non sicuro dovrebbe essere più veloce che sicuro. In generale, safe è buono perché consente al compilatore di fare ipotesi molto più forti e quindi potrebbe essere più veloce. Ma di nuovo, dipende dal codice che stai compilando, dal compilatore che stai utilizzando e da una dozzina di altri fattori.

In breve, rinuncia all'idea di poter misurare le prestazioni di una lingua. Non puoi. Una lingua non è mai " veloce " o lento " ;. Non ha una velocità.

Se hai intenzione di implementare il tuo algoritmo in modo standard, penso che sia irrilevante. Ma alcune lingue hanno legami con apis o librerie che possono darti una spinta non standard.

  1. Considera se puoi usare l'elaborazione GPU - nvidia e ati forniscono i framework CUDA e CTM e c'è uno sforzo di standardizzazione in corso da parte del gruppo khronos (openGL). Un sospetto mi dice anche che amd aggiungerà almeno un core del processore di streaming nei suoi chip futuri. Quindi penso che ci sia una vera promessa in quella zona.

  2. Prova a vedere se riesci a sfruttare le istruzioni SSE, ci sono librerie intorno, quasi tutte in C ++ o C, che forniscono utili apis, controlla il sito Intel per le utili librerie ottimizzate che ricordo "Intel Performance Primitives"; e un "kernel matematico".

Ma dal punto di vista politico, incorpora il tuo algoritmo in OpenCV in modo che anche altri possano trarne beneficio.

È una battaglia che durerà per sempre. C contro C ++ contro C # contro qualunque cosa. In C #, il concetto di non sicuro è quello di sbloccare "pericoloso". operazioni. vale a dire l'uso di puntatori e la possibilità di eseguire il cast di vuoti puntatori, ecc., come è possibile in C e C ++. Molto pericoloso e molto potente! Ma sconfiggendo su cosa si basava C #.

Scoprirai che al giorno d'oggi, Microsoft ha fatto passi da gigante nella direzione delle prestazioni, soprattutto dal rilascio di .NET, e la prossima versione di .NET supporterà effettivamente i metodi inline, come puoi fare con C ++. Ciò aumenterà le prestazioni per situazioni molto specifiche. Odio che non sarà una funzione c #, ma un brutto attributo che il compilatore raccoglie, ma non puoi avere tutto.

Personalmente, sto scrivendo un gioco con C # e gestito DirectX (perché non XNA ?? oltre lo scopo di questo post). Sto usando un codice non sicuro in situazioni grafiche, il che provoca un cenno nella direzione di ciò che altri hanno detto.

È solo perché l'accesso ai pixel è ridicolmente lento con GDI ++ che sono stato spinto a cercare alternative. Ma nel complesso, il compilatore c # è dannatamente buono, e per i confronti di codice (puoi trovare articoli) scoprirai che le prestazioni sono molto paragonabili a c ++. Questo non vuol dire che non esiste un modo migliore per scrivere il codice.

Alla fine, vedo personalmente C, C ++ e C # circa della stessa velocità durante l'esecuzione. È solo che in alcune situazioni dolorose in cui vuoi lavorare a stretto contatto con l'hardware sottostante o molto vicino a quei pixel, troverai un notevole vantaggio per la folla C / C ++.

Ma per gli affari, e la maggior parte delle cose al giorno d'oggi, C # è un vero contendente e stare all'interno del "sicuro" l'ambiente è sicuramente un vantaggio.
Quando esci, puoi fare la maggior parte delle cose con un codice non sicuro, come ho fatto io, e ragazzo, sono andato in qualche modo estremo! Ma ne è valsa la pena? Probabilmente no. Personalmente mi chiedo se avrei dovuto pensare di più sulla falsariga del codice time-critical in C ++ e su tutte le cose sicure orientate agli oggetti in C #. Ma ho prestazioni migliori di quanto pensassi di ottenere!

Finché stai attento con la quantità di chiamate interoperative che stai effettuando, puoi ottenere il meglio da entrambi i mondi. L'ho evitato personalmente, ma non so a quali costi.

Quindi un approccio che non ho provato, ma mi piacerebbe sentire avventure, usando effettivamente C ++. NET per sviluppare una libreria - sarebbe più veloce di quello pericoloso di c # per queste speciali situazioni grafiche? Come si confronta con il codice compilato C ++ nativo? Ora c'è una domanda!

Hmm ..

Se conosci il tuo ambiente e usi un buon compilatore (per l'elaborazione video su Windows, il compilatore Intel C ++ è probabilmente la scelta migliore), C ++ batterà C # a mani basse per diversi motivi:

  • L'ambiente di runtime C ++ non ha controlli di runtime intrinseci (il rovescio della medaglia è che hai il regno libero di farti esplodere). L'ambiente di runtime C # avrà alcuni controlli di integrità in corso, almeno inizialmente.
  • I compilatori C ++ sono creati per ottimizzare il codice. Mentre è teoricamente possibile implementare un compilatore C # JIT utilizzando tutto il voodo di ottimizzazione che utilizza ICC (o GCC), è dubbio che il JIT di Microsoft farà in modo affidabile meglio. Anche se il compilatore JIT ha statistiche di runtime, non è comunque buono come l'ottimizzazione guidata dal profilo in ICC o GCC.
  • Un ambiente C ++ ti consente di controllare molto meglio il tuo modello di memoria. Se l'applicazione arriva al punto di bloccare la cache di dati o frammentare l'heap, apprezzerai davvero il controllo extra sull'allocazione. Cavolo, se riesci ad evitare le allocazioni dinamiche, stai già molto meglio (suggerimento: il tempo di esecuzione di malloc () o qualsiasi altro allocatore dinamico è non deterministico, e quasi tutte le lingue non native costringono più pesante utilizzo dell'heap e quindi allocazione più pesante).

Se usi un compilatore scadente o se non puoi scegliere come target un buon chipset, tutte le scommesse sono disattivate .

Sono un po 'in ritardo nel rispondere ma posso darti un'esperienza aneddotica. Avevamo alcune routine di moltiplicazione di matrici che erano originariamente codificate in C # usando puntatori e codice non sicuro. Questo si è rivelato un collo di bottiglia nella nostra applicazione e quindi abbiamo usato il pinning + P / Invoke per chiamare una versione C ++ della routine di moltiplicazione Matrix e abbiamo ottenuto un fattore di miglioramento 2. Questo era un po 'di tempo fa con .NET 1.1, quindi ora le cose potrebbero andare meglio. Come altri sottolineano, questo non dimostra nulla, ma è stato un esercizio interessante.

Concordo anche con thAAAnos, se il tuo algoritmo deve essere "il più veloce possibile" sfruttare l'IPL o, se necessario, prendere in considerazione un'implementazione della GPU.

Ad essere onesti, in quale lingua lo scrivi non è così importante quanto gli algoritmi che usi (IMO, comunque). Magari andando al codice nativo potresti rendere la tua applicazione più veloce, ma potrebbe anche renderla più lenta - dipenderà dal compilatore, da come vengono scritti i programmi, che tipo di interoperabilità ti costa ' incorrere se si utilizza un ambiente misto, ecc. Non si può davvero dire senza profilarlo. (e, del resto, hai profilato la tua candidatura? Sai davvero dove passa il tempo? )

Un algoritmo migliore è completamente indipendente dalla lingua scelta.

L'esecuzione sulla CPU sarà sempre più veloce dell'esecuzione su una VM nella CPU. Non posso credere che le persone stiano cercando di discutere diversamente.

Ad esempio, abbiamo un lavoro di elaborazione delle immagini abbastanza pesante sul nostro server Web in coda. Inizialmente per farlo funzionare, abbiamo usato le funzioni GD di PHP.

Erano lenti da morire. Abbiamo riscritto le funzionalità di cui avevamo bisogno in C ++.

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