Pregunta

Estoy escribiendo un programa de procesamiento de imágenes para realizar el procesamiento en tiempo real de cuadros de video. Está en C # usando la biblioteca Emgu.CV (C #) que envuelve la biblioteca OpenCV dll (C ++ no administrado). Ahora tengo que escribir mi propio algoritmo especial y debe ser lo más rápido posible.

¿Cuál será una implementación más rápida del algoritmo?

  1. Escribir una función 'insegura' en C #

  2. Agregar la función a la biblioteca OpenCV y llamarla a través de Emgu.CV

Supongo que C # inseguro es más lento porque pasa por el compilador JIT, pero ¿la diferencia sería significativa?

Editar:

Compilado para .NET 3.5 bajo VS2008

¿Fue útil?

Solución

debe ser lo más rápido posible

Entonces estás haciendo la pregunta equivocada.

Codifíquelo en ensamblador, con diferentes versiones para cada variante de arquitectura importante que admita.

Use como guía la salida de un buen compilador de C ++ con optimización, porque probablemente conozca algunos trucos que usted no conoce. Pero probablemente podrá pensar en algunas mejoras, porque C ++ no necesariamente transmite al compilador toda la información que pueda ser útil para la optimización. Por ejemplo, C ++ no tiene la restricción de palabras clave C99. Aunque en ese caso en particular muchos compiladores de C ++ (incluido MSVC) ahora lo admiten, utilícelo siempre que sea posible.

Por supuesto, si quiere decir, "Quiero que sea rápido, pero no hasta el punto de salir de C # o C ++", entonces la respuesta es diferente ;-)

Esperaría que C # al menos se acerque al rendimiento de C ++ de aspecto similar en muchos casos. Supongo, por supuesto, que el programa se ejecutará el tiempo suficiente para que el tiempo que tome el JIT sea irrelevante, pero si está procesando mucho video, entonces parece probable. Pero también esperaría que haya ciertas cosas que, si las hace en C # inseguro, serán mucho más lentas que las equivalentes en C ++. No sé cuáles son, porque toda mi experiencia de JIT está en Java en lugar de CLR. También puede haber cosas que son más lentas en C ++, por ejemplo, si su algoritmo vuelve a llamar al código C #.

Desafortunadamente, la única manera de estar seguros de lo cerca que está es escribir ambos y probarlos, lo que de alguna manera pierde el punto de que escribir la versión C ++ es un esfuerzo adicional. Sin embargo, es posible que pueda obtener una idea aproximada pirateando un código rápido que se aproxime al procesamiento que desea hacer, sin necesariamente hacer todo o hacerlo bien. Si su algoritmo va a recorrer todos los píxeles y hará algunas operaciones de FP por píxel, entonces piratear un punto de referencia aproximado debería llevar media hora.

Por lo general, aconsejaría no comenzar a pensar "esto debe ser lo más rápido posible". Los requisitos deben ser alcanzables y, por definición, "lo más X posible". solo se puede alcanzar al límite. Los requisitos también deben ser comprobables, y '' tan X como sea posible '' no es comprobable a menos que de alguna manera conozca un máximo teórico. Un requisito más amigable es "esto necesita procesar fotogramas de video de tal y tal resolución en tiempo real en tal y tal CPU de velocidad" o "esto debe ser más rápido que el producto de nuestro principal competidor". Si la versión C # hace eso, con un poco de sobra para dar cuenta de problemas menores inesperados en la configuración del usuario, entonces el trabajo está hecho.

Otros consejos

Depende del algoritmo, la implementación, el compilador C ++ y el compilador JIT. Supongo que en la mayoría de los casos la implementación de C ++ será más rápida. Pero esto puede cambiar.

El compilador JIT puede optimizar su código para la plataforma en la que se ejecuta su código en lugar de un promedio para todas las plataformas en las que su código podría ejecutarse como lo hace el compilador C ++. Esto es algo en lo que las versiones más nuevas del compilador JIT son cada vez más buenas y, en algunos casos, pueden dar una ventaja al código JITted. Entonces la respuesta no es tan clara como podría esperarse. El nuevo compilador de punto de acceso Java lo hace muy bien, por ejemplo.

Otras situaciones en las que el código administrado puede funcionar mejor que C ++ es donde necesita asignar y desasignar muchos objetos pequeños. El tiempo de ejecución .net asigna previamente grandes fragmentos de memoria que se pueden reutilizar, por lo que no necesita llamar al sistema operativo cada vez que necesite asignar memoria.

No estoy seguro de que C # inseguro se ejecute mucho más rápido que C # normal. Tendrás que probar esto también.

Si desea saber cuál es la mejor solución para su situación, deberá probar ambas y medir la diferencia. No creo que haya más de

C # es típicamente más lento que C ++. Hay verificaciones de tiempo de ejecución en el código administrado. Estos son los que lo hacen manejado, después de todo. C ++ no tiene que verificar si se han excedido los límites de una matriz, por ejemplo.

Desde mi experiencia, el uso de memoria fija ayuda mucho. Hay un nuevo Clase System.IO.UnmanagedMemoryAccessor en .NET 4.0 que puede ayudar en el futuro.

Los idiomas no tienen " velocidad " ;. Depende del compilador y del código. Es posible escribir código ineficiente en cualquier idioma, y ??un compilador inteligente generará un código casi óptimo sin importar el idioma de la fuente.

El único factor realmente inevitable en el rendimiento entre C # y C ++ es que las aplicaciones C # tienen que hacer más en el inicio (cargar el marco .NET y tal vez JIT algún código), por lo que, en igualdad de condiciones, se lanzarán un poco más lento. Después de eso, depende, y no hay una razón fundamental por la cual un idioma siempre debe ser más rápido que otro.

Tampoco conozco ninguna razón por la cual C # inseguro debería ser más rápido que seguro. En general, seguro es bueno porque le permite al compilador hacer algunas suposiciones mucho más fuertes, por lo que seguro podría ser más rápido. Pero nuevamente, depende del código que esté compilando, el compilador que esté usando y una docena de otros factores.

En resumen, abandona la idea de que puedes medir el rendimiento de un idioma. No puedes Un idioma nunca es "rápido" o lento " ;. No tiene velocidad.

Si va a implementar su algoritmo de manera estándar, creo que es irrelevante. Pero algunos idiomas tienen enlaces a apis o bibliotecas que pueden darle un impulso no estándar.

  1. Considere si puede usar el procesamiento de GPU: nvidia y ati proporcionan los marcos CUDA y CTM y hay un esfuerzo continuo de estandarización del grupo khronos (openGL). Una corazonada también me dice que amd agregará al menos un núcleo de procesador de transmisión en sus futuros chips. Así que creo que hay una gran promesa en esa área.

  2. Trate de ver si puede explotar las instrucciones SSE, hay bibliotecas alrededor, la mayoría en C ++ o C, que proporcionan apis útiles, consulte el sitio de Intel para bibliotecas optimizadas y prácticas. Recuerdo Intel Performance Primitives " y un "Math Kernel".

Pero en el aspecto político, incorpore su algoritmo en OpenCV para que otros también puedan beneficiarse.

Es una batalla que durará por siempre. C versus C ++ versus C # versus lo que sea. En C #, la noción de inseguro es desbloquear "peligroso" operaciones es decir, el uso de punteros, y poder convertir a punteros vacíos, etc., como puede hacerlo en C y C ++. ¡Muy peligroso y muy poderoso! Pero derrotar en qué se basó C #.

Encontrará que hoy en día, Microsoft ha avanzado en la dirección del rendimiento, especialmente desde el lanzamiento de .NET, y la próxima versión de .NET en realidad admitirá métodos en línea, como puede hacerlo con C ++. Esto aumentará el rendimiento para situaciones muy específicas. Odio que no sea una característica de C #, sino un atributo desagradable que el compilador recoge, pero no puede tenerlo todo.

Personalmente, estoy escribiendo un juego con C # y administré DirectX (¿por qué no XNA? más allá del alcance de esta publicación). Estoy usando código inseguro en situaciones gráficas, lo que provoca un guiño en la dirección de lo que otros han dicho.

Es solo porque el acceso de píxeles es muy lento con GDI ++ que me impulsaron a buscar alternativas. Pero en general, el compilador de C # es bastante bueno, y para las comparaciones de código (puede encontrar artículos), encontrará que el rendimiento es muy comparable a C ++. Eso no quiere decir que no haya una mejor manera de escribir el código.

Al final del día, personalmente veo que C, C ++ y C # tienen aproximadamente la misma velocidad al ejecutar. Es solo que en algunas situaciones dolorosas en las que desea trabajar muy de cerca con el hardware subyacente o muy cerca de esos píxeles, encontrará una ventaja notable para la multitud de C / C ++.

Pero para los negocios, y la mayoría de las cosas hoy en día, C # es un verdadero competidor y se mantiene dentro de la "caja fuerte" el medio ambiente es definitivamente una ventaja.
Al salir, puede hacer la mayoría de las cosas con código inseguro, como lo he hecho, y vaya, ¡he llegado a algunos extremos! Pero valio la pena? Probablemente no. Personalmente, me pregunto si debería haber pensado más en las líneas de código de tiempo crítico en C ++, y todas las cosas seguras orientadas a objetos en C #. ¡Pero tengo un mejor rendimiento del que pensé que obtendría!

Mientras tengas cuidado con la cantidad de llamadas de interoperabilidad que estás haciendo, puedes obtener lo mejor de ambos mundos. Personalmente lo he evitado, pero no sé a qué costo.

Entonces, un enfoque que no he probado, pero me encantaría escuchar aventuras, al usar C ++. NET para desarrollar una biblioteca, ¿sería eso más rápido que C # no es seguro para estas situaciones gráficas especiales? ¿Cómo se compararía eso con el código compilado nativo de C ++? ¡Ahora hay una pregunta!

Hmm ..

Si conoce su entorno y utiliza un buen compilador (para el procesamiento de video en Windows, el compilador Intel C ++ es probablemente la mejor opción), C ++ vencerá a C # por varias razones:

  • El entorno de tiempo de ejecución de C ++ no tiene verificaciones de tiempo de ejecución intrínsecas (la desventaja es que tiene un reinado libre para explotar). El entorno de tiempo de ejecución de C # tendrá alguna comprobación de cordura, al menos inicialmente.
  • Los compiladores de C ++ están diseñados para optimizar el código. Si bien es teóricamente posible implementar un compilador C # JIT utilizando todo el vudú de optimización que utiliza ICC (o GCC), es dudoso que el JIT de Microsoft funcione mejor de manera confiable. Incluso si el compilador JIT tiene estadísticas de tiempo de ejecución, todavía no es tan bueno como la optimización guiada por perfil en ICC o GCC.
  • Un entorno C ++ le permite controlar su modelo de memoria mucho mejor. Si su aplicación llega al punto de destruir el caché de datos o fragmentar el montón, realmente apreciará el control adicional sobre la asignación. Demonios, si puede evitar las asignaciones dinámicas, ya está mucho mejor (pista: el tiempo de ejecución de malloc () o cualquier otro asignador dinámico no es determinista, y casi todos los idiomas no nativos son más pesados uso de almacenamiento dinámico y, por lo tanto, mayor asignación).

Si usa un compilador deficiente, o si no puede apuntar a un buen conjunto de chips, todas las apuestas están desactivadas .

Estoy un poco tarde en responder pero puedo darte una experiencia anecdótica. Teníamos algunas rutinas de multiplicación de matrices que originalmente estaban codificadas en C # usando punteros y código inseguro. Esto resultó ser un cuello de botella en nuestra aplicación y luego usamos la fijación + P / Invocar para llamar a una versión C ++ de la rutina de multiplicación de Matrix y obtuvimos un factor de mejora 2. Esto fue hace un tiempo con .NET 1.1, por lo que las cosas podrían ser mejores ahora. Como otros señalan, esto no prueba nada, pero fue un ejercicio interesante.

También estoy de acuerdo con thAAAnos, si su algoritmo realmente tiene que ser "lo más rápido posible" aprovechar IPL o, si es necesario, considerar una implementación de GPU.

Para ser honesto, en qué idioma lo escribes no es tan importante como qué algoritmos usas (IMO, de todos modos). Tal vez yendo al código nativo, podría hacer que su aplicación sea más rápida, pero también podría hacerla más lenta: dependería del compilador, cómo se escriben los programas, qué tipo de interoperabilidad le cuesta ' d incurrir si está utilizando un entorno mixto, etc. Realmente no puede decir sin perfilarlo. (y, para el caso, ¿ha perfilado su aplicación? ¿Realmente sabe dónde está pasando el tiempo? )

Un algoritmo mejor es completamente independiente del idioma que elija.

La ejecución en la CPU siempre será más rápida que la ejecución en una VM en la CPU. No puedo creer que la gente esté intentando argumentar lo contrario.

Por ejemplo, tenemos un trabajo de procesamiento de imágenes bastante pesado en nuestro servidor web que está en cola. Inicialmente para que funcionara, utilizamos las funciones GD de PHP.

Eran lentos como el infierno. Reescribimos la funcionalidad que necesitábamos en C ++.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top