suggestions propio poner historias hashtags hashtagify español crear como buscador c optimization assembly image-processing memcpy

c - propio - hashtagify.me en español



Memcpy muy rápido para el procesamiento de imágenes? (6)

Cortesía de William Chan y Google. 30-70% más rápido que memcpy en Microsoft Visual Studio 2005.

void X_aligned_memcpy_sse2(void* dest, const void* src, const unsigned long size) { __asm { mov esi, src; //src pointer mov edi, dest; //dest pointer mov ebx, size; //ebx is our counter shr ebx, 7; //divide by 128 (8 * 128bit registers) loop_copy: prefetchnta 128[ESI]; //SSE2 prefetch prefetchnta 160[ESI]; prefetchnta 192[ESI]; prefetchnta 224[ESI]; movdqa xmm0, 0[ESI]; //move data from src to registers movdqa xmm1, 16[ESI]; movdqa xmm2, 32[ESI]; movdqa xmm3, 48[ESI]; movdqa xmm4, 64[ESI]; movdqa xmm5, 80[ESI]; movdqa xmm6, 96[ESI]; movdqa xmm7, 112[ESI]; movntdq 0[EDI], xmm0; //move data from registers to dest movntdq 16[EDI], xmm1; movntdq 32[EDI], xmm2; movntdq 48[EDI], xmm3; movntdq 64[EDI], xmm4; movntdq 80[EDI], xmm5; movntdq 96[EDI], xmm6; movntdq 112[EDI], xmm7; add esi, 128; add edi, 128; dec ebx; jnz loop_copy; //loop please loop_copy_end: } }

Es posible que pueda optimizarlo aún más según su situación exacta y cualquier suposición que pueda hacer.

También es posible que desee verificar la fuente de memcpy (memcpy.asm) y quitarle el manejo especial de casos. ¡Es posible optimizar aún más!

Estoy procesando imágenes en C que requieren copiar grandes cantidades de datos en la memoria: la fuente y el destino nunca se superponen.

¿Cuál es la forma más rápida absoluta de hacerlo en la plataforma x86 utilizando GCC (donde SSE , SSE2 pero NO SSE3 están disponibles)?

¿Espero que la solución esté en ensamblaje o utilizando intrínsecos de GCC?

Encontré el siguiente enlace, pero no tengo idea de si es la mejor manera de hacerlo (el autor también dice que tiene algunos errores): http://coding.derkeiler.com/Archive/Assembler/comp.lang.asm.x86/2006-02/msg00123.html

EDITAR: tenga en cuenta que es necesaria una copia, no puedo evitar tener que copiar los datos (podría explicar por qué, pero le ahorraré la explicación :))


El código SSE publicado por hapalibashi es el camino a seguir.

Si necesita aún más rendimiento y no se aparta de la larga y tortuosa ruta de escribir un controlador de dispositivo: todas las plataformas importantes hoy en día tienen un controlador DMA que es capaz de hacer un trabajo de copia más rápido y en paralelo al código de la CPU podría hacer.

Eso implica escribir un controlador sin embargo. Ningún gran SO del que sea consciente expone esta funcionalidad al usuario debido a los riesgos de seguridad.

Sin embargo, puede valer la pena (si necesita el rendimiento) ya que ningún código en la tierra podría superar a una pieza de hardware diseñada para realizar tal trabajo.


En cualquier nivel de optimización de -O1 o superior, GCC usará definiciones integradas para funciones como memcpy - con el parámetro right -march ( -march=pentium4 para el conjunto de características que usted menciona) debería generar código en línea bastante específico para la arquitectura.

Lo compararía y vería lo que sale.


Esta pregunta tiene cuatro años y estoy un poco sorprendido de que nadie haya mencionado el ancho de banda de la memoria todavía. CPU-Z informa que mi máquina tiene PC3-10700 RAM. Que la RAM tiene un ancho de banda máximo (también conocido como tasa de transferencia, rendimiento, etc.) de 10700 MBytes / seg. La CPU en mi máquina es una CPU i5-2430M, con una frecuencia máxima de turbo de 3 GHz.

Teóricamente, con una CPU infinitamente rápida y mi RAM, memcpy podría ir a 5300 MBytes / seg , es decir, la mitad de 10700 porque memcpy tiene que leer y luego escribir en la RAM. (Editar: Como v.oddou señaló, esta es una aproximación simplista).

Por otro lado, imagina que tenemos RAM infinitamente rápida y una CPU realista, ¿qué podríamos lograr? Usemos mi CPU de 3 GHz como ejemplo. Si pudiera hacer una lectura de 32 bits y una de 32 bits, escribir cada ciclo, entonces podría transferir 3e9 * 4 = 12000 MBytes / seg . Esto parece fácilmente al alcance de una CPU moderna. Ya podemos ver que el código que se ejecuta en la CPU no es realmente el cuello de botella. Esta es una de las razones por las que las máquinas modernas tienen cachés de datos.

Podemos medir lo que la CPU realmente puede hacer mediante la evaluación comparativa de memcpy cuando sabemos que los datos están en caché. Hacer esto con precisión es complicado. Hice una aplicación simple que escribía números aleatorios en una matriz, los remecía a otra matriz y luego sumaba los datos copiados. Pasé por el código en el depurador para asegurarme de que el compilador inteligente no haya eliminado la copia. Alterar el tamaño de la matriz altera el rendimiento de la memoria caché: pequeñas matrices encajan en la memoria caché, y las grandes no tanto. Obtuve los siguientes resultados:

  • Arrays de 40 KByte: 16000 MBytes / sec
  • Matrices de 400 KByte: 11000 MBytes / sec
  • Matrices de 4000 KByte: 3100 MBytes / sec

Obviamente, mi CPU puede leer y escribir más de 32 bits por ciclo, ya que 16000 es más que los 12000 que calculé anteriormente. Esto significa que la CPU es aún menos un cuello de botella de lo que pensaba. Utilicé Visual Studio 2005, y entrando en la implementación estándar de memcpy, puedo ver que usa la instrucción movqda en mi máquina. Supongo que esto puede leer y escribir 64 bits por ciclo.

El bonito código hapalibashi publicado alcanza 4200 MBytes / seg en mi máquina, aproximadamente un 40% más rápido que la implementación VS 2005. Supongo que es más rápido porque usa la instrucción de captación previa para mejorar el rendimiento de la memoria caché.

En resumen, el código que se ejecuta en la CPU no es el cuello de botella y ajustar ese código solo hará pequeñas mejoras.


Si es específico de los procesadores Intel, puede beneficiarse de IPP . Si sabe que se ejecutará con una GPU Nvidia, quizás pueda usar CUDA ; en ambos casos, es mejor parecer más amplio que optimizar memcpy (), ya que ofrece oportunidades para mejorar su algoritmo a un nivel superior. Ambos son sin embargo dependientes de hardware específico.


Si está en Windows, use las API de DirectX , que tiene rutinas GPU específicas optimizadas para el manejo de gráficos (¿qué tan rápido podría ser?) Su CPU no está cargada. Haga algo más mientras la GPU lo mastica.

Si quieres ser un OS agnóstico, prueba OpenGL .

No juegue con el ensamblador, ya que es muy probable que fracase miserablemente al superar a los ingenieros de software con más de 10 años de experiencia en creación de bibliotecas.