¿Por qué Skylake es mucho mejor que Broadwell-E en cuanto a rendimiento de memoria de un solo subproceso?

Resuelto aggieNick02 asked hace 8 años • 2 respuestas

Tenemos una prueba comparativa 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 la RAM (DDR4-2133) iguales. No estamos hablando de unos pocos 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 está compilado en la versión VS2015 e informa el tiempo promedio para completar cada memcpy en:

64 bits: 2,2 ms para Skylake frente a 4,5 ms 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 software de evaluación comparativa y validan lo que muestra este ejemplo simple: 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();
}
aggieNick02 avatar Sep 01 '16 05:09 aggieNick02
Aceptado

El ancho de banda de la memoria de un solo subproceso en las CPU modernas está limitado por max_concurrency / latencylas 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 hacia/desde L1D. (Y 16 entradas de "supercola" que rastrean líneas hacia/desde L2).

(Actualización: los experimentos muestran que Skylake probablemente tiene 12 LFB, frente a los 10 de Broadwell. Por ejemplo, Fig7 en el documento 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 para L3/memoria que los chips de escritorio/portátiles de cuatro núcleos o de doble núcleo, por lo que el ancho de banda de memoria de un solo subproceso es en realidad mucho peor en un Xeon grande, aunque el ancho de banda agregado máximo con muchos subprocesos 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 de "escritorio de gama alta") es realmente malo para esto: la latencia L3/memoria es significativamente mayor que para Broadwell-E/Broadwell-EP, por lo que el ancho de banda de un solo subproceso es aún peor que en un Broadwell con un número de núcleos similar. (SKX usa una malla en lugar de un bus de anillo porque se escala mejor; consulte esto para obtener detalles sobre ambos . Pero aparentemente los factores constantes son malos en el nuevo diseño; tal vez las generaciones futuras tengan un mejor ancho de banda/latencia L3 para recuentos de núcleos pequeños/medianos. Sin embargo, el L2 privado por núcleo aumenta a 1MiB, por lo que tal vez el L3 sea intencionalmente lento para ahorrar energía).

(El cliente Skylake (SKL) como en la pregunta, y los chips posteriores de escritorio/portátil de cuatro núcleos/hexagonales 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 lo hacemos. saber con certeza qué hará el cliente de Ice Lake).


Un chip de cuatro o dos núcleos solo necesita un par de subprocesos (especialmente si los núcleos + uncore (L3) tienen una frecuencia alta) para saturar el ancho de banda de su memoria, y un Skylake con doble canal DDR4 rápido tiene bastante ancho de banda.

Para obtener más información sobre esto, consulte la sección Plataformas vinculadas a la latencia de esta respuesta sobre el ancho de banda de memoria x86. (Y lea las otras partes para memcpy/memset con bucles SIMD versus rep movs/rep stostiendas NT versus tiendas RFO normales, y más).

También relacionado: ¿ Qué todo programador debería saber 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).

Peter Cordes avatar Dec 13 '2017 06:12 Peter Cordes

Finalmente puse en funcionamiento VTune (evaluación). Proporciona una puntuación vinculada a DRAM de .602 (entre 0 y 1) en Broadwell-E y .324 en Skylake, y una gran parte del retraso de Broadwell-E proviene de la latencia de la memoria. Dado que las tarjetas de memoria tienen la misma velocidad (excepto el canal dual configurado en Skylake y el canal cuádruple en Broadwell-E), mi mejor suposición es que algo en el controlador de memoria en Skylake es tremendamente mejor.

Hace que comprar la arquitectura Broadwell-E sea una decisión mucho más difícil y requiere que realmente necesite núcleos adicionales para siquiera considerarla.

También obtuve recuentos de fallos L3/TLB. En Broadwell-E, el recuento de errores de TLB fue aproximadamente un 20 % mayor y el recuento de errores de L3 fue aproximadamente un 36 % mayor.

No creo que esto sea realmente una respuesta al "por qué", así que no la marcaré como tal, pero es lo más cercano que creo que estaré a una por el momento. Gracias por todos los comentarios útiles a lo largo del camino.

aggieNick02 avatar Sep 15 '2016 18:09 aggieNick02