2009-08-08 15 views
25

Sto cercando di sviluppare un'applicazione che elaborerà i dati da una telecamera line-scan a circa 2000 linee (frame) al secondo. Per questa applicazione in tempo reale, sento che C/C++ è la strada da percorrere. (È un mio sentimento, e altri saranno d'accordo che il codice gestito non è giusto per questo compito.)Programma C++ veloce, C# GUI, possibile?

Tuttavia, ho fatto molto piccolo MFC, o qualsiasi altra GUI C++. Comunque sto facendo davvero bene le C# GUI.

Quindi mi sembra naturale scrivere il codice ad alta intensità di dati in C/C++ e la GUI in C#. La GUI sarà utilizzata per il monitoraggio di set-up/calibrazione/on-line (ed eventualmente per l'output di dati via UDP, perché è più semplice in C#.

Quindi, per prima cosa, vorrei vedere se qualcuno è d'accordo che questo sarebbe Sulla base della mia esperienza di programmazione (buona con algoritmi C di basso livello e progettazione GU # C di alto livello), mi sembra giusto

In secondo luogo, non sono sicuro che il modo giusto per andare Ho appena creato una soluzione in VS2005, che chiama alcune funzioni DLL (extern "C" da un'app C#. E per assicurarmi di poterlo fare, ho scritto alcune variabili globali nella DLL e ho letto loro:

test.h

int globaldata; 
extern "C" __declspec(dllexport) void set(int); 
extern "C" __declspec(dllexport) int get(); 

test.cpp

extern int data=0; 
__declspec(dllexport) void set(int num) { 
    data = num; 
} 

__declspec(dllexport) int get() { 
    return data; 
} 

Test.cs

[DllImport("test")] 
private static extern void set(int num); 

[DllImport("test")] 
private static extern int get(); 

Calling get() e set() opera correttamente (get() restituisce il numero che ho passato a set()).

Ora, so che è possibile esportare una classe C++, ma deve essere gestita? Come funziona? Sto andando su questo nel modo giusto?

Grazie per tutto il vostro aiuto!

*** EDIT ***

Prima di tutto, GRAZIE per le risposte fantastiche finora! Sono sempre incredibilmente colpito da Stack Overflow ...

Immagino che una cosa su cui avrei dovuto puntare di più, non fosse necessariamente velocità raw (questo può essere prototipato e benchmark). Una cosa che mi preoccupa di più è il comportamento non deterministico del Garbage Collector. Questa applicazione dovrebbe non essere tollerante di un ritardo di 500 ms durante l'esecuzione di garbage collection.

Io sono tutto per la codifica e provare questo in puro C#, ma se so in anticipo che il GC e qualsiasi altro comportamento .NET non deterministico (?) Causerà un problema, penso che il mio tempo sarebbe meglio speso codificandolo in C/C++ e comprendendo la migliore interfaccia C#.

+1

Per ridurre le preoccupazioni sulla raccolta dei rifiuti "Generalmente le raccolte di 2 (il tipo costoso) non si verificano fino a quando la memoria non è sotto pressione. richiama sempre gli oggetti IDisposable e NON chiama manualmente GC.Colect()), quindi non dovresti riscontrare notevoli ritardi. –

+1

@Mitch. Nella mia esperienza, ho visto che le raccolte G2 si verificano molto spesso su una memoria non vincolata sistema che non era spesso inattivo. Controlla il contatore perfmon per vedere di persona, GC succede molto più di quanto pensi che sia. È ancora abbastanza veloce sull'hardware moderno, ma potrebbe non essere abbastanza buono per l'OP. – gbjbaanb

risposta

30
+3

Questo è uno dei C# maggiori vantaggi rispetto a Java ... ** puntatori **. – Kredns

+5

Per quanto ne so .NET * still * non suppor t istruzioni SIMD. Mono, ma questa è una piccola storia diversa. Quindi sì, su alcune attività il C++, specialmente compilato con ICC, sarà significativamente più veloce. – Ray

+1

@Ray: in senso stretto la questione non riguardava se .NET non supporta le istruzioni SIMD .... –

0

La lingua che scegli non influisce sulle prestazioni (ad esempio, puoi influire sulla velocità del 5/10%). Ciò che farà la differenza sono gli algoritmi che userete, come elaborate i dati, profilate la vostra applicazione, ecc ... (le prestazioni potrebbero cambiare con un rapporto di 10x).

1

Sono d'accordo con Mitch al 100%.

Se dopo aver esaminato le sue risorse, si sente ancora che è necessario utilizzare un codice non gestito, è possibile scrivere un livello "business" in C++ (o in questo caso, in realtà un livello funzionale) e scrivere l'interfaccia utente in C#. Utilizzare COM Interop per chiamare da C#/codice gestito al codice non gestito.

Ancora una volta, però, la mia sensazione è che non sarà necessario farlo.

2

Per C++ si utilizza C++/CLI, che in realtà non è così male. È molto meglio delle vecchie estensioni gestite.

Per commentare prestazioni. Dipende davvero. Quanto avanti e indietro ci sarà tra il tuo codice C++ e il tuo codice C#? Avrai una discussione in background che raccoglie dati in C++ e che periodicamente li invii al codice C#? Se stai per interagire con un dispositivo, userà seriale, USB, qualche API che ti è stata data?

+0

Sì, ce l'hai. Il thread in background raccoglierà i dati dal frame buffer sulla telecamera e riassemblerà l'immagine e farà i calcoli. Quindi periodicamente il C# eseguirà il polling (o il C++ richiamerà?) Per fornire alcuni dati, e l'app C# lo invierà tramite il socket UDP. L'interfaccia dipende dall'hardware che selezioniamo, ma quello che stavo osservando era USB 2.0 e hanno fornito l'API C++. È gestito C++/CLI? Di nuovo, sono preoccupato per il GC non deterministico che causa ritardi sporadici mentre manipolo una grande quantità di dati. –

+0

Le prestazioni dipendono anche da altri fattori: ad esempio, l'implementazione C++/CLI di STL è terribilmente lenta, quindi i contenitori .NET hanno prestazioni migliori. – gbjbaanb

5

La prima cosa che devi fare è testare il tuo assunto. Quali sono i tuoi limiti di rendimento? Che tipo di hardware ti aspetti di ospitare l'applicazione? Scrivi un piccolo programma in C# che si occupa del problema principale e misurare la velocità con cui viene eseguito.

Solo una volta che hai i fatti puoi prendere una decisione sull'uso o meno di C/C++ su una soluzione gestita.

Insieme ad altri che hanno commentato, ho il sospetto che una soluzione gestita in C# andrà benissimo, specialmente se si utilizza lo .NET Parallel Extensions.

Se si finisce per passare al percorso C/C++, sono disponibili due opzioni di reinterop, ovvero pInvoke e COM interop. Non credo che ci sia un modo pulito per accedere alle classi C++ non gestite direttamente da .NET; a tal fine, dovresti considerare implementing a managed/unmanaged C++ assembly.

+1

Le soluzioni C++ possono usare OpenMP (estensioni parallele) più o meno semplici – Ray

+0

E le app C# possono usare estensioni parallele o .net4, che non è troppo lontano da OpenMP – erikkallen

+0

OpenMP, o semplicemente boost :: threads o TBB: https://event.on24.com/event/36/88/3/rt/1/index.html?&eventid=36883&sessionid=1 – gbjbaanb

6

Per applicazione in tempo reale: vi consiglio di C++, si sarà più flessibile, con la gestione della memoria, più veloce, e anche multi-piattaforma a seconda di ciò quadro è usato ...!

Chi quadro e GUI, vi consiglio di avere uno sguardo Qt. Qt è un ottimo framework per lo sviluppo di software C++.

Immagino sia la soluzione al tuo problema!

+1

Mi piace Qt, ma penso che una GUI in C# sia ancora la scelta migliore, proprio per WPF . – MasterMastic

15

Secondo me la soluzione è un suono uno:

  1. Anche se C# è veloce non è mai in grado di competere con un non gestito C ben scritto/C++, ho fatto applicazioni ad alte prestazioni a me stesso che lo dimostra al di là di i piccoli esempi che le persone postano sempre quando qualcuno invia questi tipi di dichiarazioni
  2. MFC o ATL UI di programmazione è ingombrante e lento, C# è il modo di andare qui, non ho mai farò programmazione MFC/ATL UI mai più, a meno costretto a

tuo soluzione, nel caso in cui non l'hai ancora capito, si chiama "Mixed Mode", che in pratica significa che si combina il codice gestito (C#) e Unmanaged (C/C++) negli stessi progetti, spesso è un po ' fastidio per ottenere il progetto VS up-and-running (errori LNK2020..argh ..) ma quando trovi le giuste impostazioni dovrebbe funzionare bene.

L'unica cosa negativa è che i moduli in modalità mista devono funzionare in Full Trust, se va bene, allora penso che si sa cosa fare.

Un altra cosa si potrebbe desiderare di guardare è un progetto open source chiamato SWIG. SWIG prende il codice C/C++ e crea un assembly .NET, lo ho usato io stesso nel mio progetto open source TM++. Vedi qui per maggiori informazioni su SWIG http://www.swig.org/.

+0

Ho visto alcune persone nominare SWIG prima ... una cosa di cui mi preoccupo è il processo di sviluppo ... Sto pensando di scrivere sia la GUI che l'app principale allo stesso tempo (la GUI permettendomi di vedere cosa succede nell'app principale). Con SWIG, sembra che potrei continuamente ri-SWIG prima di poter fare qualsiasi cosa con esso dalla GUI C#. È questo il caso? Penso che VS dovrebbe essere in grado di gestire qualcosa di simile con facilità, no? –

+0

In genere non è necessario modificare il file di definizione dell'interfaccia SWIG, è sufficiente aggiungere i file di intestazione C/C++ e, in alcuni casi, è necessario eseguire operazioni avanzate, ma nella maggior parte dei casi SWIG eseguirà la scansione delle intestazioni. Ecco un esempio di un file di definizione dell'interfaccia SWIG: http://tmplusplus.svn.sourceforge.net/viewvc/tmplusplus/trunk/src/TMPlusPlus.i?revision=350 –

+0

..e per creare l'assembly .NET. puoi fare qualcosa del genere: swig -C++ -csharp -outdir ./SWIG -lcpointer.i TMPlusPlus.i dove TMPlusPlus.i è il file di definizione dell'interfaccia SWIG sopra. –

4

La mia azienda fa qualcosa di molto simile, anche se con telecamere CCD invece di telecamere line-scan. Stiamo utilizzando C# per la GUI, la comunicazione di rete, "plumbing" di alto livello e C++/CLI per gli algoritmi di basso livello. Funziona abbastanza bene. Non sarai mai in grado di scrivere un vero sistema in tempo reale con tempi di risposta massimi garantiti su Windows, ma dalla mia esperienza il GC sarà l'ultimo dei tuoi problemi qui. Per prima cosa, il GC viene eseguito solo quando si assegna memoria; così fa malloc/new in C/C++, e anche loro hanno bisogno di tempo (pensate alla frammentazione della memoria). Dalle misurazioni effettuate, un GC completo impiega 10-50 ms e non interromperà necessariamente gli altri thread durante quel periodo (a meno che non provino ad allocare la memoria gestita, penso), il che è ok per noi. Ma non sono sicuro che questi numeri possano essere generalizzati a qualsiasi tipo di applicazione, probabilmente dovresti fare il tuo profilo personale per essere sicuro.

Se temete che la vostra GUI possa violare i vostri vincoli in tempo reale, potreste considerare di mettere l'elaborazione dell'immagine in un processo separato e comunicare con la GUI usando pipe/socket. O almeno tieni a mente questa opzione quando progetti il ​​tuo sistema, così hai l'opzione peggiore, se ti imbatti in problemi di prestazioni imprevedibili.

La tua seconda domanda era se dovessi usare C++ o C# per gli algoritmi attuali. Personalmente, mi sento più comforatble in C++ quando scrivo algoritmi complessi di elaborazione delle immagini.Penso che il linguaggio sia più adatto per il compito, e ci sono molte più librerie di numerazione per C/C++ che per C#. Ma potrebbe essere una questione di preferenze personali. Dal punto di vista delle prestazioni, C++ ha il vantaggio che il C++ inliner è migliore di .NET JIT inliner (cioè può inline più delle tue piccole chiamate di funzione).

Se si sceglie di utilizzare C++, suggerirei di utilizzare C++/CLI: in tal modo, è possibile scrivere classi C++ che vengono compilate nel codice gestito. L'ottimizzatore C++ li ottimizzerà, solo l'ultimo passaggio di compilazione al codice nativo sarà fatto da .NET JIT. Il grande vantaggio è che è possibile accedere direttamente alle classi .NET da C++/CLI e creare facilmente classi gestite in C++/CLI a cui è possibile accedere da C#. Non è necessario scrivere codice wrapper su entrambi i lati del recinto. (C++/CLI è un po 'goffo perché contiene costrutti linguistici per la programmazione gestita e non gestita, ma se hai già familiarità con C++ e C# non gestiti, probabilmente non avrai problemi a capirlo.)

+1

"e si possono facilmente creare classi gestite in C++/CLI a cui si può accedere da C#" così, ho fatto questo, ma cosa succede se voglio codice non gestito per la parte di elaborazione dati? Nel mio codice C++/CLI, immagino che scriverei la classe non gestita per fare tutto, e quindi un'interfaccia C++/CLI che il C# chiama e può accedere al mio C++ "puro"? Ancora un po 'confuso qui ... –

+0

Questo dipende molto dal tuo problema. Scrivere classi non gestite + wrapper gestiti in C++/CLI è unidirezionale. È anche possibile scrivere piccole funzioni di helper non gestite e chiamare quelle da una classe gestita più ampia. Il compilatore C++/CLI può emettere IL e codice nativo, può compilare C++ "normale" e ha parole chiave speciali per creare classi gestite. Le classi gestite possono chiamare nel codice non gestito/creare classi non gestite e viceversa. Il modo in cui lo usi dipende da te. – Niki

0

I L'ho fatto con C++. NET

Dato che sia C++. NET che C# sono gestiti, non vedo perché non potrebbe essere fatto. Il punto è come lo farai.

Il mio scanner aveva fino a 3000 linee/sec ma la strategia chiave era quella di visualizzare blocchi di 32 linee alla volta. Non avevo requisiti rigidi in tempo reale, quindi a volte potrei essere un po 'indietro. Se il tempo reale è molto importante per te, dovresti prendere in considerazione la possibilità di cambiare piattaforma.

C'è una soluzione Windows in tempo reale chiamata "InTime OS" ma è davvero dolorosa da usare.

Un altro approccio che si può avere è quello di separare il duro tempo reale in una DLL o libreria separata e fare in modo che C# mostri ciò che può a sua velocità. Davvero, l'utente non sarà mai in grado di dire se l'interfaccia ha 2000 fps o 500 fps

-3

Perché Windows? Ha prestazioni di memoria orribili e una rete peggiore rispetto a tutti gli Unix disponibili. L'acquisizione specializzata di un sensore di linea implica che è necessario un dispositivo per gestire l'input non elaborato. Considerare innanzitutto l'utilizzo del sistema operativo corretto, che ridurrà di molto le altre pressioni da affrontare (sono molto familiare con le tecnologie dello scanner di linea).

+1

Forse non vuole provare a parlare ai suoi clienti con l'esecuzione di qualcos'altro rispetto a Windows? – erikkallen

+0

+1: preoccuparsi della latenza dei GC mentre stai ancora utilizzando Windows è sciocco. –

+0

Prestazioni di memoria orribili? Dai un'occhiata a questa domanda: [Prestazioni di Memory Cache .Net 4.0] (http://stackoverflow.com/questions/11729023/memory-cache-net-4-0-performance-test-astonishing-result) – lsalamon

-1

Ho un'esperienza nei sistemi nativi di latenza molto bassa C/C++ e C#.

  • in C/C++ 80% del tempo di processore è perduto nei metodi malloc deterministici, ma il codice nativo è 10 volte più veloce di codice MSIL

  • in C allocazione # memoria è più veloce perché si tratta di un processo asynchrone

la scelta deve essere fatta dal rapporto: tempo di processo/malloc numero

Così granularità !!!

La soluzione per C/C++ è pre-alloc ALLS buffer nella memoria (uso prelettura cache L2/L3 se necessario)

La soluzione per C# è minimizzare P-Invoke meccanismo di conversione

Complimenti per la vostra progetto, Paul

+0

-1 " il codice nativo è 10 volte più veloce del codice msil ". Allora stai sbagliando. –

-1

Il front-end wpf e C++ backend (pinvoke) è veloce ma quando si esegue la GUI sui thread, il thread della GUI non viene bloccato dal codice di background.Quando lo fai, il tuo programma sembrerà più veloce e leggero.