performance - ¿Por qué Skylake es mucho mejor que Broadwell-E para el rendimiento de memoria de un solo subproceso?
x86 benchmarking (2)
Finalmente conseguí VTune (evaluación) en funcionamiento. Otorga un puntaje de DRAM de .602 (entre 0 y 1) en Broadwell-E y .324 en Skylake, con una gran parte del retraso de Broadwell-E proveniente de la latencia de memoria. Dado que las tarjetas de memoria tienen la misma velocidad (excepto el doble canal configurado en Skylake y el cuádruple canal en Broadwell-E), mi mejor conjetura es que algo sobre el controlador de memoria en Skylake es tremendamente mejor.
Hace que comprar en la arquitectura Broadwell-E sea una decisión mucho más difícil y requiere que realmente necesite los núcleos adicionales para siquiera considerarlo.
También obtuve recuentos de fallas L3 / TLB. En Broadwell-E, el recuento de fallas TLB fue aproximadamente un 20% más alto y el recuento de fallas L3 aproximadamente un 36% más alto.
No creo que esta sea realmente una respuesta para "por qué", así que no lo marcaré como tal, pero está tan cerca como creo que llegaré a una por el momento. Gracias por todos los comentarios útiles en el camino.
Tenemos un punto de referencia de rendimiento de memoria simple. Todo lo que hace es memcpy repetidamente para un gran bloque de memoria.
Al observar los resultados (compilados para 64 bits) en algunas máquinas diferentes, las máquinas Skylake funcionan significativamente mejor que Broadwell-E, manteniendo el sistema operativo (Win10-64), la velocidad del procesador y la velocidad de RAM (DDR4-2133) iguales. No estamos hablando de algunos puntos porcentuales, sino de un factor de aproximadamente 2 . Skylake está configurado en doble canal, y los resultados para Broadwell-E no varían para doble / triple / cuádruple canal.
Alguna idea de por qué esto esta pasando? El código que sigue se compila en la versión VS2015 e informa el tiempo promedio para completar cada memoria en:
64 bits: 2.2ms para Skylake vs 4.5ms para Broadwell-E
32 bits: 2.2 ms para Skylake frente a 3.5 ms para Broadwell-E .
Podemos obtener un mayor rendimiento de la memoria en una compilación Broadwell-E de cuatro canales utilizando múltiples subprocesos, y eso es bueno, pero ver una diferencia tan drástica para el acceso a la memoria de un solo subproceso es frustrante. ¿Alguna idea sobre por qué la diferencia es tan pronunciada?
También hemos utilizado varios programas de evaluación comparativa, y validan lo que muestra este simple ejemplo: el rendimiento de la memoria de un solo subproceso es mucho mejor en Skylake.
#include <memory>
#include <Windows.h>
#include <iostream>
//Prevent the memcpy from being optimized out of the for loop
_declspec(noinline) void MemoryCopy(void *destinationMemoryBlock, void *sourceMemoryBlock, size_t size)
{
memcpy(destinationMemoryBlock, sourceMemoryBlock, size);
}
int main()
{
const int SIZE_OF_BLOCKS = 25000000;
const int NUMBER_ITERATIONS = 100;
void* sourceMemoryBlock = malloc(SIZE_OF_BLOCKS);
void* destinationMemoryBlock = malloc(SIZE_OF_BLOCKS);
LARGE_INTEGER Frequency;
QueryPerformanceFrequency(&Frequency);
while (true)
{
LONGLONG total = 0;
LONGLONG max = 0;
LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds;
for (int i = 0; i < NUMBER_ITERATIONS; ++i)
{
QueryPerformanceCounter(&StartingTime);
MemoryCopy(destinationMemoryBlock, sourceMemoryBlock, SIZE_OF_BLOCKS);
QueryPerformanceCounter(&EndingTime);
ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;
ElapsedMicroseconds.QuadPart *= 1000000;
ElapsedMicroseconds.QuadPart /= Frequency.QuadPart;
total += ElapsedMicroseconds.QuadPart;
max = max(ElapsedMicroseconds.QuadPart, max);
}
std::cout << "Average is " << total*1.0 / NUMBER_ITERATIONS / 1000.0 << "ms" << std::endl;
std::cout << "Max is " << max / 1000.0 << "ms" << std::endl;
}
getchar();
}
El
ancho de banda de memoria de un
solo subproceso
en las CPU modernas está limitado por la
max_concurrency / latency
de las transferencias desde L1D al resto del sistema, no por los cuellos de botella del controlador DRAM.
Cada núcleo tiene 10 Buffers de relleno de línea (LFB) que rastrean las solicitudes pendientes a / desde L1D.
(Y 16 entradas "superqueue" que rastrean líneas hacia / desde L2).
(Actualización: los experimentos muestran que Skylake probablemente tiene 12 LFB, en comparación con 10 en Broadwell. Por ejemplo, Fig7 en el documento de ZombieLoad , y otros experimentos de rendimiento, incluidas las pruebas de @ BeeOnRope de múltiples flujos de tiendas )
Los chips de muchos núcleos de Intel tienen una mayor latencia a L3 / memoria que los chips de escritorio / laptop de cuatro núcleos o de doble núcleo, por lo que el ancho de banda de la memoria de un solo hilo es mucho peor en un Xeon grande, a pesar de que el ancho de banda agregado máximo con muchos hilos es mucho mejor. Tienen muchos más saltos en el bus de anillo que conecta núcleos, controladores de memoria y el Agente del sistema (PCIe, etc.).
SKX (Skylake-server / AVX512, incluidos los chips i9 "high-end desktop") es realmente malo para esto: L3 / latencia de memoria es significativamente mayor que para Broadwell-E / Broadwell-EP, por lo que el ancho de banda de un solo hilo es aún peor que en un Broadwell con un recuento de núcleos similar. (SKX usa una malla en lugar de un bus de anillo porque eso se escala mejor, vea esto para obtener detalles sobre ambos . Pero aparentemente los factores constantes son malos en el nuevo diseño; tal vez las generaciones futuras tendrán un mejor ancho de banda / latencia L3 para recuentos de núcleos pequeños / medianos Sin embargo, el L2 privado por núcleo aumenta hasta 1MiB, por lo que tal vez L3 sea intencionalmente lento para ahorrar energía).
(Skylake-client (SKL) como en la pregunta, y más tarde los chips de escritorio / laptop quad / hex-core como Kaby Lake y Coffee Lake, todavía usan el diseño de bus de anillo más simple. Solo cambiaron los chips del servidor. Todavía no sepa con seguridad qué hará el cliente de Ice Lake).
Un chip quad o dual core solo necesita un par de subprocesos (especialmente si los núcleos + uncore (L3) tienen una frecuencia alta) para saturar su ancho de banda de memoria, y un Skylake con un canal dual DDR4 rápido tiene bastante ancho de banda.
Para obtener más información al respecto, consulte la sección Plataformas vinculadas a la latencia de
esta respuesta
sobre ancho de banda de memoria x86.
(Y lea las otras partes para memcpy / memset con bucles SIMD versus
rep movs/rep stos
, y NT stores versus tiendas RFO regulares, y más).
También relacionado: ¿Qué debe saber todo programador sobre la memoria? (Actualización de 2017 sobre lo que sigue siendo cierto y lo que ha cambiado en ese excelente artículo de 2007).