2011-03-24 5 views
5

Quiero desarrollar algunos códigos de procesamiento de imágenes y me pregunto si hay una gran diferencia entre desarrollarlos en C++ y C#?¿Qué factores debo considerar al elegir entre C# y C++ para un proyecto de procesamiento de imágenes?

¿Hay algún documento detallado que explique qué es bueno implementar en C# y qué es bueno implementar en C++?

Hasta donde yo sé, dado que el código C# se compila en código máquina justo antes de ejecutarlo (utilizando el compilador .NET CLR JIT), no debería haber mucha diferencia entre los dos lenguajes si durante el desarrollo del código el lenguaje específico sugiere implementar un patrón de diseño (por ejemplo, usar mucho nuevo versus usar arreglos fijos).

Editar: Hay algunos otros parámetros que no pensé al principio, pero estoy buscando en el momento cuando leí algunas de las respuestas: 1- Es un alto nivel de proyectos que significa que puedo pedir a la el usuario tiene una computadora muy buena (Una gran cantidad de memoria y procesadores multi-core) 2- Puedo suponer que el usuario tiene una tarjeta gráfica muy buena, por lo que puedo usar su GPU para el procesamiento. 3- Creo que WPF es bueno para este desarrollo (¿Estoy en lo cierto?). ¿Hay alguna biblioteca similar para C++? Trabajé con MFC, pero no estoy seguro de que MFC sea tan bueno como WPF cuando se trabaja en proyectos que necesitan mostrar imágenes y la GUI es muy importante.

+1

Montaje de lejos ... –

+6

Escriba el programa completo en ambos idiomas. Ejecute una gran cantidad de pruebas automatizadas en múltiples configuraciones de hardware, sistema operativo y compilador. Descartar los valores atípicos. Disfruta tu respuesta. –

+0

No es tan fácil como eso. El costo total depende de los costos de hardware, tiempo de desarrollo, etc. El rendimiento en la mayoría de los casos no es tan importante, ya que a menudo es más barato comprar otro servidor en lugar de tener que codificar en un lenguaje de bajo nivel (lo que lleva más tiempo). – jgauffin

Respuesta

5

.NET IL está compilado en código máquina, igual que C++. Pero casi siempre el código de C++ será más rápido, debido a que:

  • El tiempo de compilación se convierte en parte del tiempo de ejecución (sólo una vez, pero a veces esto es un problema)
  • JIT-compiladores pasan menos tiempo en la optimización de AOT -compiladores, por el motivo mencionado anteriormente. Por lo tanto, el código generado por un JIT es generalmente más lento. Por ejemplo, los JIT por lo general no vectorizan nada, lo cual es importante para el procesamiento de imágenes. En la mayoría de los casos, ni siquiera es posible generar código vectorizado debido a restricciones de VM (Mono.Simd es una excepción)
  • Los idiomas en una VM deben garantizar que el programa no se escape de la VM. Por ejemplo, tienen que verificar los límites de la matriz en cada acceso (a menos que el compilador pueda demostrar que el índice está siempre dentro del rango, tenga en cuenta que los compiladores JIT no dedican mucho tiempo a dichos análisis).
  • Para núcleos críticos en el tiempo, puede insertar instrucciones de ensamblador usted mismo. Las máquinas virtuales no permiten esto porque el ensamblador puede salir de la máquina virtual.

En algunos casos, el código administrado puede ser más rápido que el código no administrado:

  • Un colector garbarge permite que la memoria que se asignará más eficiente que malloc. Pero, a menos que la memoria solo se use por un corto tiempo, sin embargo, Mark-And-Sweep también necesita algo de tiempo.
  • Un JIT puede compilar código con más suposiciones estáticas en el código (como, conoce todas las posibles implementaciones de una función virtual) y rehacer las compilaciones cuando la suposición ya no se cumple. Esto se hace en Java HotSpot, pero no en JIT ni Mono de Microsoft.

Resumen: Si la velocidad de ejecución es importante, use C++. Pero C# puede ser rápido suficiente, como muestra Paint.NET. También considere la opción de codificar principalmente en C# y una vez que no esté satisfecho con la velocidad de alguna función importante, vuelva a implementarla en C++/CIL o llame a su función optimizada usando P/Invoke.

+0

El ejemplo de Paint.NET es probablemente la parte más útil de esta respuesta. –

+0

@Mark: El crédito va para Steve Haigh, mencionó primero a Paint.NET – Meinersbur

0

Depende de qué tan bueno eres en ambos idiomas, si eres realmente un experto en programación de procesamiento de imágenes o algoritmo, C++ te dará más libertad para tus optimizaciones acrobáticas. Pero si usted no es ese experto, segura mediante el uso de lenguaje de alto nivel

+0

Buen punto, conclusión incorrecta. ** Si no es tan experto, sálvese reutilizando una biblioteca existente. ** –

0

Hay algunos factores a considerar ...

¿Existen bibliotecas que es posible que desee utilizar - si existen y son .Net entonces eso puede influenciar su decisión a favor de C#.

Sin embargo, creo que es seguro decir que las aplicaciones numéricas más intensas (y el procesamiento de imágenes es básicamente operaciones numéricamente intensivas en una matriz 2D) se escribirían en código nativo. Hay una muy buena excepción a esto: echarle un vistazo a Paint.Net, está escrito casi en su totalidad en código administrado y tiene una excelente funcionalidad y rendimiento (http://getpaint.net).

¿Cuál es el propósito de su aplicación? Si es un "pasatiempo" o ejercicio de aprendizaje, entonces elija el idioma con el que se sienta más feliz. Si se trata de una aplicación comercial, primero examinaría las opciones de la biblioteca.

3

Como alguien que ha convertido una biblioteca de procesamiento de imágenes de C++ a C# y ha hecho los puntos de referencia, el lenguaje tiene poca influencia en la velocidad de lo que está haciendo, más importantes son los algoritmos que está utilizando y qué api está utilizando para manipular las imágenes (es decir, en Windows use bits de seguridad en el mapa de bits). Logré ganar incrementos significativos de velocidad debido al hecho de que es posible escribir código más paralelo mucho más fácil en C# que en C++ y la capacidad de no estar atascado solo con Monitor. Espera (Admitiré que no soy un C++ experto en enhebrado, de hecho no soy un aficionado al enhebrado C++) pero con una amplia variedad de opciones para paralelizar fácilmente las operaciones (que en gráficos son bastante intrínsecas) para aumentar la velocidad masiva al convertir de C++ a C# (además de tener que preocuparme sobre liberar recursos y no sobre la memoria, hizo la vida mucho más fácil también). Obviamente, si te sientes cómodo con C++, puedes escribir código más rápido en C++, pero conoces C++ y SIMD bastante bien para vencer al compilador de C#.También debería tener en cuenta que convertimos de C++ a C# suponiendo que perdiéramos aproximadamente 10% de velocidad, y la razón por la que convertimos fue el costo a la hora de agregar nuevas características era tan alta que una reescritura en C# valió la pena, el producto final que terminó siendo más rápido fue solo una ventaja (ahora también debo mencionar que la biblioteca original se escribió antes de la extensión SIMD donde se agregó a Visual C++, por lo que su uso no estaba disponible para el autor original de la biblioteca).

+0

Hola Kris, ¿esta biblioteca de procesamiento de imágenes está disponible en cualquier lugar? : O –

+0

No, es interno ... –

1

Si bien tiene la certeza de que el código .NET se compila con JIT en código máquina, debe tener en cuenta que tiene muy poco control sobre ese proceso. No puede elegir el conjunto de instrucciones objetivo, y aunque el código administrado afirma que la compilación JIT es superior porque puede usar el conjunto de instrucciones más rápido disponible por máquina, el hecho es que esto aún no se ha implementado .

En pocas palabras: Puede escribir código C++ utilizando instrucciones SSE que se ejecutarán 4 veces más rápido que el código generado por JIT en la misma CPU.


Algunas otras cosas que vale la pena mencionar: el paralelismo SIMD es mucho más fácil de escribir, y mucho más fácil para el compilador para optimizar, de múltiples hilos. No hay sobrecarga con SIMD, pero la sincronización de subprocesos no es gratuita. Y hay menos errores ocultos con SIMD, por lo que es mucho más fácil obtener una aceleración lineal. Es TAN fácil para múltiples hilos caer en la compartición de la línea de caché y contención. Y los lenguajes administrados no le dan absolutamente ningún control sobre compartir falsamente.

Sí, C# hace que sea más fácil hacer subprocesos múltiples. Mal. C++ hace que sea mucho más factible hacer multiprocesamiento correctamente, y puede obtener la velocidad suficiente para sintonizar el código de un solo subproceso que ni siquiera necesita para manejar la complejidad adicional de los subprocesos.

Si usted está decidido a optimizar usted mismo, aquí hay algunas técnicas: (detenerse en cualquier punto a lo largo de la línea una vez que haya alcanzado el rendimiento deseado, ya que cuanto más se aplica la más compleja su código será)

  1. Trabaja en los datos brutos, no uses alguna API que agregue direccionamiento indirecto y abstracción sobre un montón de píxeles. Esto no solo puede ralentizarte, sino que también interfiere con el siguiente grupo de mejoras. (Kris alluded to LockBits vs SetPixel, la rutina nativa para el acceso de imagen sin formato es GetDIBits)

  2. Ajuste de la caché. Un enfoque simple es desenrollar el ciclo más interno por un factor de 16 aproximadamente. A continuación, invierta el orden de anidamiento del bucle. Esto dará como resultado el procesamiento de fragmentos rectangulares de los datos, que generalmente son interdependientes, por lo que accede a cada dato muchas veces por cada relleno de caché. Sin embargo, es una pérdida utilizar un generador de perfiles de caché en esta etapa.

  3. Use SIMD. Procesa 4 o más veces tantos píxeles en cada iteración de bucle. Victoria fácil. Especialmente dado que ya ha desenrollado el bucle, esas instrucciones idénticas están ahí sentadas pidiendo que se combinen. Pero no se puede hacer hasta que te liberes de las abstracciones.

  4. Ahora use un generador de perfiles de caché. Las capturas SIMD tienen características significativamente diferentes a las instrucciones escalares, por lo que debes hacer esto después de la conversión SIMD.

  5. Quizás multihilo. Si el problema es realmente grande Preste especial atención a los tamaños de líneas de caché. Y trate de nunca escribir en los datos que otros hilos también usan. Definitivamente no escribes los mismos datos de múltiples hilos.

Cuestiones relacionadas