optimization memcpy powerpc shark altivec

optimization - ¿Qué hace que el Apple PowerPC memcpy sea tan rápido?



shark altivec (5)

He escrito varias funciones de copia en busca de una buena estrategia de memoria en PowerPC. El uso de los registros Altivec o fp con sugerencias de caché (dcb *) duplica el rendimiento en un simple bucle de copia de bytes para datos grandes. Inicialmente complacido con eso, introduje un memcpy regular para ver cómo se comparaba ... ¡10 veces más rápido que el mejor! No tengo la intención de volver a escribir memcpy, pero espero aprender de él y acelerar varios filtros de imagen simples que pasan la mayor parte de su tiempo moviendo píxeles hacia y desde la memoria.

El análisis de tiburones revela que su bucle interno usa dcbt para precapturar, con 4 lecturas vectoriales y luego 4 escrituras vectoriales. Después de ajustar mi mejor función para también transportar 64 bytes por iteración, la ventaja de rendimiento de memcpy sigue siendo embarazosa. Estoy usando dcbz para liberar ancho de banda, Apple no usa nada, pero ambos códigos tienden a dudar en las tiendas.

prefetch dcbt future dcbt distant future load stuff lvx image lvx image + 16 lvx image + 32 lvx image + 48 image += 64 prepare to store dcbz filtered dcbz filtered + 32 store stuff stvxl filtered stvxl filtered + 16 stvxl filtered + 32 stvxl filtered + 48 filtered += 64 repeat

¿Alguien tiene alguna idea sobre por qué un código muy similar tiene una brecha de rendimiento tan dramática? ¡Me encantaría marinar los filtros de imagen reales en cualquier salsa secreta que memcpy esté usando!

Información adicional: Todos los datos están alineados por vector. Estoy haciendo copias filtradas de la imagen, no reemplazando la original. El código se ejecuta en PowerPC G4, G5 y Cell PPU. La versión de Cell SPU ya es increíblemente rápida.


El análisis de tiburones revela que su bucle interno usa dcbt para precapturar, con 4 lecturas vectoriales y luego 4 escrituras vectoriales. Después de ajustar mi mejor función para también arrastrar 64 bytes por iteración

Puede que esté indicando lo obvio, pero como no menciona lo siguiente en su pregunta, puede valer la pena señalarlo:

Apostaría a que la elección de 4 vectores de Apple seguida de escrituras de 4 vectores tiene tanto que ver con la tubería del G5 y su gestión de la ejecución de instrucciones fuera de orden en "grupos de despacho" como con un perfecto mágico de 64 bytes tamaño de línea. ¿Notaste que la línea salta en los enlaces enlazados de Nick Bastin? Esto significa que el desarrollador pensó en cómo el G5 consumiría el flujo de instrucciones. Si desea reproducir el mismo rendimiento, no es suficiente leer datos de 64 bytes a la vez, debe asegurarse de que sus grupos de instrucciones estén bien llenos (básicamente, recuerdo que las instrucciones se pueden agrupar hasta en cinco independientes, con el Las primeras cuatro son instrucciones de no salto y la quinta solo puede ser un salto. Los detalles son más complicados).

EDITAR: también puede interesarle el siguiente párrafo en la misma página:

La instrucción dcbz aún tiene ceros alineados en segmentos de 32 bytes de memoria según G4 y G3. Sin embargo, dado que no es un cacheline completo en un G5, no tendrá los beneficios de rendimiento que probablemente esperaba. Hay una instrucción dcbzl recientemente introducida para el G5 que pone a cero una línea de caché completa de 128 bytes.


Aún no es una respuesta, ¿pero verificó que memcpy en realidad está moviendo los datos? Tal vez solo fue reasignado copia en escritura. Aún verías el bucle interno de memcpy en Shark como parte de la primera y la última página que realmente se copian.


Como se mencionó en otra respuesta, "dcbz", tal como lo define Apple en el G5, solo funciona con 32 bytes, por lo que perderá el rendimiento con esta instrucción en un G5 que tiene 128 bytes de licenciatura. Debe usar "dcbzl" para evitar que la cacheline de destino se recupere de la memoria (y reduzca efectivamente el ancho de banda de la memoria de lectura útil a la mitad).


No sé exactamente lo que estás haciendo, ya que no puedo ver tu código, pero la salsa secreta de Apple está here .


Tal vez sea debido al almacenamiento en caché de la CPU. Intenta ejecutar CacheGrind :

Cachegrind es un perfilador de caché. Realiza una simulación detallada de los cachés I1, D1 y L2 en su CPU, por lo que puede identificar con precisión las fuentes de las fallas de caché en su código. Identifica el número de errores de caché, referencias de memoria e instrucciones ejecutadas para cada línea de código fuente, con resúmenes por función, por módulo y por todo el programa. Es útil con programas escritos en cualquier idioma. Cachegrind ejecuta programas alrededor de 20--100x más lentos de lo normal.