Esta pregunta continúa sobre mi pregunta aquí (con el consejo de Mystical):
Rendimiento del bucle de código C
Continuando con mi pregunta, cuando uso instrucciones empaquetadas en lugar de instrucciones escalares, el código que usa intrínsecos se vería muy similar:
for(int i=0; i<size; i+=16) {
y1 = _mm_load_ps(output[i]);
…
y4 = _mm_load_ps(output[i+12]);
for(k=0; k<ksize; k++){
for(l=0; l<ksize; l++){
w = _mm_set_ps1(weight[i+k+l]);
x1 = _mm_load_ps(input[i+k+l]);
y1 = _mm_add_ps(y1,_mm_mul_ps(w,x1));
…
x4 = _mm_load_ps(input[i+k+l+12]);
y4 = _mm_add_ps(y4,_mm_mul_ps(w,x4));
}
}
_mm_store_ps(&output[i],y1);
…
_mm_store_ps(&output[i+12],y4);
}
El rendimiento medido de este kernel es de aproximadamente 5.6 operaciones FP por ciclo, aunque esperaría que sea exactamente 4 veces el rendimiento de la versión escalar, es decir, 4.1,6 = 6,4 operaciones FP por ciclo.
Teniendo en cuenta el movimiento del factor de peso (gracias por señalarlo), el programa se ve así:
Parece que el programa no cambia, aunque hay una instrucción adicional después de la movss
operación que mueve el valor de peso escalar al registro XMM y luego usa shufps
para copiar este valor escalar en todo el vector. Parece que el vector de peso está listo para usarse por el mulps
momento, teniendo en cuenta la latencia de conmutación de la carga al dominio de punto flotante, por lo que esto no debería incurrir en ninguna latencia adicional.
Las instrucciones movaps
(alineadas, empaquetadas) addps
y mulps
que se usan en este kernel (verificadas con código ensamblador) tienen la misma latencia y rendimiento que sus versiones escalares, por lo que tampoco deberían incurrir en una latencia adicional.
¿Alguien tiene una idea de dónde se gasta este ciclo adicional por 8 ciclos, asumiendo que el rendimiento máximo que puede obtener este kernel es 6.4 operaciones FP por ciclo y se está ejecutando a 5.6 operaciones FP por ciclo?
Por cierto, aquí está el aspecto del ensamblaje real:
…
Block x:
movapsx (%rax,%rcx,4), %xmm0
movapsx 0x10(%rax,%rcx,4), %xmm1
movapsx 0x20(%rax,%rcx,4), %xmm2
movapsx 0x30(%rax,%rcx,4), %xmm3
movssl (%rdx,%rcx,4), %xmm4
inc %rcx
shufps $0x0, %xmm4, %xmm4 {fill weight vector}
cmp $0x32, %rcx
mulps %xmm4, %xmm0
mulps %xmm4, %xmm1
mulps %xmm4, %xmm2
mulps %xmm3, %xmm4
addps %xmm0, %xmm5
addps %xmm1, %xmm6
addps %xmm2, %xmm7
addps %xmm4, %xmm8
jl 0x401ad6 <Block x>
…
fuente
shufps
instrucción agrega 1 ciclo cada 1.6 iteraciones?" Eso es difícil ...shufps
debería estar directamente disponible para lamultps
operación, ya que ambos son dominios FPRespuestas:
Intente usar la creación de perfiles EMON en Vtune o alguna herramienta equivalente como oprof
Perfilado EMON (Monitoreo de eventos) => como una herramienta basada en el tiempo, pero puede decirle qué evento de rendimiento está causando el problema. Sin embargo, primero debe comenzar con un perfil basado en el tiempo, para ver si hay una instrucción en particular que sobresalga. (Y posiblemente los eventos relacionados que le dicen con qué frecuencia hubo un puesto de retiro en esa IP).
Para utilizar el perfil EMON, debe ejecutar una lista de eventos, que van desde "los sospechosos habituales" hasta ...
Aquí, comenzaría con errores de caché, alineación. No sé si el procesador que está utilizando tiene un contador para las limitaciones del puerto de RF, debería hacerlo, pero agregué la creación de perfiles EMON hace mucho tiempo, y no sé qué tan bien se mantienen al agregar eventos apropiados para la microarquitectura.
También es posible que se trate de una entrada, búsqueda de instrucciones, parada. ¿Cuántos bytes hay en estas instrucciones, de todos modos? También hay eventos EMON para eso.
Responder al comentario de que Nehalem VTune no puede ver eventos L3: no es cierto. Aquí hay cosas que estaba agregando para comentar, pero no encajaban:
En realidad, HAY contadores de rendimiento para el LL3 / L3 $ / llamado Uncore. Me sorprendería inmensamente si VTune no los admite. Ver http://software.intel.com/sites/products/collateral/hpc/vtune/performance_analysis_guide.pdfapunta a VTune y otras herramientas como PTU. De hecho, incluso sin eventos LL3, como dice David Levinthal: "el procesador Intel® Core ™ i7 tiene un" evento de latencia "que es muy similar al evento EAR de datos de la familia de procesadores Itanium®. Este evento muestra cargas, registrando el número de ciclos entre la ejecución de la instrucción y la entrega real de los datos. Si la latencia medida es mayor que la latencia mínima programada en MSR 0x3f6, bits 15: 0, entonces el contador se incrementa. El desbordamiento del contador arma el mecanismo PEBS y en el siguiente evento que satisface el umbral de latencia, la latencia medida, la dirección virtual o lineal y la fuente de datos se copian en 3 registros adicionales en el búfer PEBS. Debido a que la dirección virtual se captura en una ubicación conocida, el controlador de muestreo también podría ejecutar una traducción virtual a física y capturar la dirección física. La dirección física identifica la ubicación de la casa de NUMA y, en principio, permite un análisis de los detalles de las ocupaciones de la memoria caché ". También señala, en la página 35, eventos de VTune como L3 CACHE_HIT_UNCORE_HIT y L3 CACHE_MISS_REMOTE_DRAM. A veces es necesario buscar el valor numérico códigos y programarlos en la interfaz de nivel inferior de VTune, pero creo que en este caso es visible en la bonita interfaz de usuario.
OK, en http://software.intel.com/en-us/forums/showthread.php?t=77700&o=d&s=lr un programador de VTune en Rusia (creo) "explica" que no se puede probar en Uncore eventos.
Está equivocado: podría, por ejemplo, habilitar solo una CPU y muestrear de manera significativa. También creo que existe la posibilidad de marcar los datos faltantes de L3 a medida que regresan a la CPU. De hecho, en general, el L3 sabe a qué CPU está devolviendo datos, por lo que definitivamente puede muestrear. Es posible que no sepa qué hyperthread, pero nuevamente puede deshabilitarlo y pasar al modo de un solo hilo.
Pero parece que, como es bastante común, tendría que trabajar ALREDEDOR de VTune, no con él, para hacer esto.
Pruebe primero el perfil de latencia. Eso está completamente dentro de la CPU, y es poco probable que la gente de VTune lo haya estropeado demasiado.
Y, repito, lo más probable es que su problema esté en el núcleo, no en L3. Entonces VTune debería ser capaz de manejar eso.
Intente "Contabilidad cíclica" según Levinthal.
fuente
off-core
parte del núcleo, por lo que no hay contadores de eventos de rendimiento disponibles para esta parte. Por lo tanto, es difícil estimar las pérdidas de caché, etcétera.