2009-08-08 18 views
25

Estoy buscando desarrollar una aplicación que procese datos de una cámara de escaneo de línea de alrededor de 2000 líneas (cuadros) por segundo. Para esta aplicación en tiempo real, creo que C/C++ es el camino a seguir. (Es mi opinión, y otros estarán de acuerdo en que el código administrado no es el adecuado para esta tarea).¿Es posible el programa Fast C++, C# GUI?

Sin embargo, he hecho muy poco MFC o cualquier otra GUI de C++. Sin embargo, realmente estoy haciendo muy bien las GUI de C#.

Me parece natural escribir el código de datos intensivos en C/C++ y la GUI en C#. La GUI se usará para la configuración/calibración/monitoreo en línea (y posiblemente para la salida de datos vía UDP, porque es más fácil en C#.

Primero, me gustaría ver si alguien está de acuerdo en que esto Sea el camino a seguir. De acuerdo con mi experiencia en programación (buena en algoritmos C de bajo nivel y diseño de GUI de alto nivel en C#), me parece bien.

En segundo lugar, no estoy seguro de cómo hacerlo. Acerca de esto. Acabo de lanzar una solución en VS2005, que llama a algunas (DLL "C") funciones de una aplicación C#. Y para asegurarme de que podía hacerlo, escribí algunas variables globales en la DLL, y leí de ellos:

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() y set() trabajo correctamente (get() devuelve el número que pasé a set()).

Ahora, sé que también puede exportar una clase de C++, pero ¿tiene que administrarse? ¿Cómo funciona? ¿Voy por esto de la manera correcta?

¡Gracias por toda su ayuda!

*** EDIT ***

En primer lugar, GRACIAS para sus fantásticas respuestas hasta el momento! Siempre estoy increíblemente impresionado con Stack Overflow ...

Supongo que una cosa que debería haber tocado más, no era necesariamente la velocidad bruta (esto puede ser un prototipo y un punto de referencia). Una cosa que me preocupa más es el comportamiento no determinista del Garbage Collector. Esta aplicación podría no tolerar una demora de 500 ms mientras se realiza la recolección de basura.

Estoy todo por codificar y probar esto en C# puro, pero si sé de antemano que el GC y cualquier otro comportamiento .NET no determinista (?) Causarán un problema, creo que mi tiempo sería mejor pasó codificando en C/C++ y descubriendo la mejor interfaz de C#.

+0

Esto suena como un proyecto realmente genial –

+1

Para ayudar a reducir sus preocupaciones sobre la recolección de basura "Generación 2 colecciones (el tipo costoso), normalmente no sucederá hasta que la memoria esté bajo presión. Si su aplicación es un buen ciudadano .NET (es decir, siempre llama a deshacerse de los objetos IDisposables, y NO llama manualmente a GC.Colect()), entonces no debería experimentar grandes retrasos. –

+1

@Mitch. No en mi experiencia, he visto que las colecciones de G2 ocurren muy a menudo en una memoria no limitada sistema que no solía estar inactivo. Verifique el contador perfmon para verlo por sí mismo, GC ocurre mucho más de lo que cree. Aún es bastante rápido en hardware moderno, pero puede no ser lo suficientemente bueno para el OP. – gbjbaanb

Respuesta

30
+3

Ese es uno de C# mayores ventajas sobre Java ... ** punteros **. – Kredns

+5

Por lo que yo sé .NET * todavía * no apoya t instrucciones SIMD. Mono lo hace, pero esa es una historia diferente. Así que sí en algunas tareas C++ especialmente compilado con ICC será significativamente más rápido. – Ray

+1

@Ray: estrictamente hablando, la pregunta no era si .NET no es compatible con las instrucciones SIMD ... –

0

El idioma que elija no afectará mucho al rendimiento (supongamos que puede afectar la velocidad en un 5/10%). Lo que marcará la diferencia son los algoritmos que usará, cómo procesa datos, perfila su aplicación, etc. (el rendimiento podría cambiar con una proporción de 10x).

1

Estoy de acuerdo con Mitch 100%.

Si después de investigar sus recursos, todavía siente que necesita usar algún código no administrado, puede escribir una capa "comercial" en C++ (o en este caso realmente una capa funcional) y escribir su UI en C#. Use COM Interop para llamar desde C#/código administrado a su código no administrado.

De nuevo, sin embargo, mi sensación es que no necesitarás hacer esto.

2

Para C++ utiliza C++/CLI, que en realidad no es tan malo. Es mucho mejor que las antiguas extensiones administradas.

Para comentar sobre el rendimiento. Realmente depende. ¿Cuánto de ida y vuelta habrá entre tu código C++ y tu código C#? ¿Tendrás un hilo de fondo recopilando datos en C++ y enviándolos periódicamente al código C#? Si va a interactuar con un dispositivo, ¿usará una serie, USB, alguna API que se le haya proporcionado?

+0

Sí, lo tienes. El hilo de fondo recopilará datos del búfer de cuadros en la cámara y volverá a ensamblar la imagen y hará cálculos. Entonces periódicamente el C# sondeará (o el C++ lo devolverá?) Para proporcionar algunos datos, y la aplicación C# lo enviará a través del socket UDP. La interfaz depende del hardware que seleccionamos, pero la que he estado viendo es USB 2.0 y proporcionan la API de C++. ¿Se administra C++/CLI? Una vez más, me preocupa que el GC no determinista cause retrasos esporádicos ya que manipulo una gran cantidad de datos. –

+0

El rendimiento también depende de otros factores; por ejemplo, la implementación de C++/CLI de STL es tremendamente lenta, hasta el punto de que los contenedores .NET la superan. – gbjbaanb

5

Lo primero que debe hacer es probar su suposición. ¿Cuáles son tus limitaciones de rendimiento? ¿Qué tipo de hardware esperas para alojar la aplicación? Escriba un pequeño programa en C# que se ocupe del problema central y mida qué tan rápido se ejecuta.

Solo una vez que tenga los hechos puede tomar una decisión acerca de si usar o no C/C++ sobre una solución administrada.

Junto con otros que han comentado, sospecho que una solución administrada C# funcionará bien, especialmente si utiliza el .NET Parallel Extensions.

Si termina yendo por la ruta C/C++, entonces hay dos opciones re interop, es decir, pInvoke y COM interop. No creo que exista una manera clara de acceder directamente a las clases de C++ no administradas desde .NET; para este fin, debe considerar implementing a managed/unmanaged C++ assembly.

+1

Las soluciones C++ pueden usar OpenMP (extensiones paralelas) igual de fácil – Ray

+0

Y las aplicaciones C# pueden usar extensiones paralelas, o .net4, que no está demasiado lejos de OpenMP – erikkallen

+0

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

6

Para aplicaciones en tiempo real: Recomiendo C++, será más flexible con la administración de la memoria, más rápido, e incluso multiplataforma, dependiendo de qué marco se use ...!

Sobre el marco y la GUI, le recomiendo que eche un vistazo a Qt. Qt es un gran marco para el desarrollo de software C++.

¡Supongo que es la solución a su problema!

+1

Me gusta Qt, pero creo que una GUI en C# sigue siendo la mejor opción, solo por WPF . – MasterMastic

15

En mi opinión su solución es un sonido uno:

  1. A pesar de que C# es rápido que nunca podrá competir con un C no administrado bien escrito/C++, he hecho aplicaciones de alto rendimiento a mí mismo que demuestra esto más allá los pequeños ejemplos que las personas siempre publican cuando alguien publica este tipo de declaraciones
  2. MFC o ATL La programación UI es engorrosa y lenta, C# es el camino a seguir aquí, NUNCA volveré a hacer la programación UI MFC/ATL, a menos que sea forzado a

Su solución, en caso de que aún no lo hayas descifrado, se llama "Modo mixto", lo que básicamente significa que combinas código administrado (C#) y no administrado (C/C++) en los mismos proyectos, a menudo es un poco molestia para poner en marcha el proyecto VS (errores LNK2020 ... alto ...) pero cuando encuentre la configuración correcta debería funcionar bien.

Lo único negativo es que los ensamblados de modo mixto deben ejecutarse en plena confianza, si eso está bien, entonces supongo que sabes qué hacer.

Otra cosa que quizás quiera ver es un proyecto de código abierto llamado SWIG. SWIG toma tu código C/C++ y crea un ensamblado .NET a partir de él, lo he usado yo mismo en mi proyecto de código abierto TM++. Consulte aquí para obtener más información sobre SWIG http://www.swig.org/.

+0

He visto a algunas personas mencionar SWIG antes ... una cosa que me preocupa es el proceso de desarrollo ... Estoy planeando el tipo de escritura de la GUI y la aplicación principal al mismo tiempo (la GUI permitiéndome ver qué está pasando en la aplicación principal). Con SWIG, parece que podría tener que volver a SOCORRECERLO continuamente antes de poder hacer nada con él desde la GUI de C#. ¿Es este el caso? Creo que VS debería ser capaz de manejar algo como esto con facilidad, ¿no? –

+0

Normalmente no tiene que cambiar el archivo de definición de interfaz SWIG, solo necesita agregar sus archivos de encabezado C/C++, y en algunos casos debe hacer cosas avanzadas, pero en la mayoría de los casos SWIG escaneará sus encabezados. Aquí hay un ejemplo de un archivo de definición de interfaz SWIG: http://tmplusplus.svn.sourceforge.net/viewvc/tmplusplus/trunk/src/TMPlusPlus.i?revision=350 –

+0

..y para hacer su ensamblado .NET puede hacer algo como esto: swig -C++ -csharp -outdir ./SWIG -lcpointer.i TMPlusPlus.i donde TMPlusPlus.i es el archivo de definición de interfaz SWIG anterior. –

4

Mi empresa hace algo muy similar, aunque con cámaras CCD en lugar de cámaras con escáner de línea. Estamos usando C# para la GUI, comunicación de red, "plomería" de alto nivel y C++/CLI para los algoritmos de bajo nivel. Funciona bastante bien. Nunca podrá escribir un verdadero sistema en tiempo real con tiempos de respuesta máximos garantizados en Windows, pero según mi experiencia, el GC será el menor de sus problemas aquí. Por un lado, el GC solo se ejecuta cuando asigna memoria; también lo hace malloc/new en C/C++, y también necesitan tiempo (piense en la fragmentación de la memoria). A partir de las mediciones que hemos realizado, un GC completo tarda de 10 a 50 ms y no necesariamente detendrá los otros subprocesos durante ese tiempo (a menos que intenten asignar memoria administrada, creo), lo que está bien para nosotros. Pero no estoy seguro de si estos números se pueden generalizar a cualquier tipo de aplicación, es probable que deba hacer su propio perfil para estar seguro.

Si tiene miedo de que su GUI pueda romper sus restricciones en tiempo real, puede considerar poner el procesamiento de imágenes real en un proceso separado y comunicarse con la GUI usando pipes/Sockets. O al menos tenga en cuenta esa opción cuando diseñe su sistema, de modo que lo tenga como la peor opción posible, si realmente se encuentra con problemas de rendimiento imprevistos.

Su segunda pregunta fue si debería usar C++ o C# para los algoritmos actuales. Personalmente, me siento más cómodo en C++ cuando escribo complejos algoritmos de procesamiento de imágenes.Creo que el lenguaje es más adecuado para la tarea, y hay muchas más librerías para C/C++ que para C#. Pero eso podría ser una cuestión de preferencia personal. Desde el punto de vista del rendimiento, C++ tiene la ventaja de que el inline de C++ es mejor que el inline de .NET JIT (es decir, puede alinear más de sus pequeñas llamadas de función).

Si opta por utilizar C++, le sugiero que use C++/CLI: De esta manera, puede escribir clases de C++ compiladas en código administrado. El optimizador de C++ los optimizará, solo el último paso de compilación al código nativo será realizado por .NET JIT. La gran ventaja es que puede acceder directamente a sus clases .NET desde C++/CLI, y puede crear fácilmente clases administradas en C++/CLI a las que se puede acceder desde C#. No necesita escribir el código de envoltura en ambos lados de la guía. (C++/CLI es un poco torpe porque contiene construcciones de lenguaje para programación administrada y no administrada, pero si ya está familiarizado con C++ no administrado y C#, probablemente no tenga ningún problema para entenderlo)

+1

"y puede crear fácilmente clases administradas en C++/CLI a las que se puede acceder desde C#" , así que lo he hecho, pero ¿qué sucede si deseo un código no administrado para la parte de procesamiento de datos? En mi código C++/CLI, supongo que escribiría la clase no administrada para hacer todo, y luego una interfaz C++/CLI a la que llama C#, y puedo acceder a mi C++ "puro". Todavía estoy un poco confundido aquí ... –

+0

Eso realmente depende de su problema. Escribir clases no administradas + envoltorios administrados en C++/CLI es de una sola manera. También es posible escribir pequeñas funciones auxiliares no administradas y llamar a aquellas de una clase administrada más grande. El compilador C++/CLI puede emitir código IL y nativo, puede compilar C++ "normal" y tiene palabras clave especiales para crear clases administradas. Las clases administradas pueden llamar al código no administrado/crear clases no administradas y viceversa. Cómo lo usa realmente depende de usted. – Niki

0

I Lo he hecho con C++ .NET

Dado que tanto C++ .NET como C# se administran, no veo por qué no se pudo hacer. El punto es cómo lo harás.

Mi escáner tenía hasta 3000 líneas/seg. Pero la estrategia clave era mostrar bloques de 32 líneas a la vez. No tenía requisitos duros en tiempo real, así que a veces podía estar un poco rezagado. Si el tiempo real es muy importante para ti, debes considerar cambiar de plataforma.

Hay una solución de Windows en tiempo real llamada "InTime OS" pero es realmente doloroso de usar.

Otro enfoque que puede tener es separar el disco duro en tiempo real en un dll o biblioteca independiente y hacer que el C# muestre lo que pueda a su propia velocidad. Realmente, el usuario nunca podrá saber si su interfaz tiene 2000 fps o 500 fps

-3

¿Por qué Windows? Tiene un rendimiento de memoria horrible y peor red en comparación con cualquiera de los Unixes que hay. La captura especializada de un sensor de línea implica que necesita un dispositivo para manejar la entrada sin procesar. Considera usar primero el sistema operativo correcto, lo que reducirá en gran medida las otras presiones con las que tendrás que lidiar (estoy muy familiarizado con las tecnologías de escáner de línea).

+1

¿Quizás no quiera intentar convencer a sus clientes de que ejecuten algo más que Windows? – erikkallen

+0

+1: Preocuparse por la latencia del GC mientras todavía está ejecutando Windows es una tontería. –

+0

¿Un rendimiento de memoria horrible? Eche un vistazo a esta pregunta: [Memoria Caché. Rendimiento de .NET 4.0] (http://stackoverflow.com/questions/11729023/memory-cache-net-4-0-performance-test-astonishing-result) – lsalamon

-1

Tengo una experiencia en sistemas de latencia muy bajos C/C++ y C# nativos.

  • en C/C++ 80% de tiempo de procesador se pierde en los métodos malloc deterministas, pero el código nativo es 10 veces más rápido que el código msil

  • en C asignación # memoria es más rápido debido a que es un proceso asincrónico

Su elección debe ser realizada por la relación: tiempo de proceso/malloc número

Así Granularidad !!!

La solución para C/C++ es pre-alloc alls buffers en la memoria (uso de captación previa L2/L3 caché si es necesario)

La solución para C# es minimizar mecanismo de conversión P-Invoke

Felicitaciones por su proyecto, Paul

+0

-1 " el código nativo es 10 veces más rápido que el código msil ". Entonces lo estás haciendo mal. –

-1

Front-end wpf y C++ backend (pinvoke) es rápido pero cuando tu GUI también trabaja en hilos, tu hilo GUI no se bloquea con tu código de fondo.Cuando lo haga, su programa se verá más rápido y ligero.