0 votos

Tengo 8 núcleos lógicos, ¿por qué el valor de machdep.cpu.logical_per_package es 16?

Tengo un MacBook Pro de 15 pulgadas "Core i7" 2.8 Mid-2015, corriendo Catalina 10.15.7 - especificaciones detalladas aquí: https://everymac.com/systems/apple/macbook_pro/specs/macbook-pro-core-i7-2.8-15-dual-graphics-mid-2015-retina-display-specs.html

Mi pregunta es sobre el significado de algunas de las variables que aparecen cuando ejecuto sysctl -a .

Mi entendimiento es que tengo 1 paquete de CPU, 4 núcleos, y 8 núcleos lógicos (implementados con hyperthreading, así que 2 hyperthreads por núcleo), correspondientes a estas variables, que todas tienen sentido para mí:

hw.packages: 1
hw.physicalcpu: 4
hw.physicalcpu_max: 4
hw.logicalcpu: 8
hw.logicalcpu_max: 8

Sin embargo, no entiendo el significado de estas variables aparentemente relacionadas:

machdep.cpu.logical_per_package: 16
machdep.cpu.cores_per_package: 8
machdep.cpu.core_count: 4
machdep.cpu.thread_count: 8

Eso parece: machdep.cpu.core_count: 4 corresponde al número de núcleos físicos, machdep.cpu.thread_count: 8 corresponde al número de "hyperthreads", y machdep.cpu.cores_per_package: 8 corresponde al número de núcleos "virtuales" que ve el sistema operativo. (¿Estas dos últimas variables tendrán siempre el mismo valor? ¿Cuál es la diferencia entre núcleos (virtuales) por paquete y número de hilos)?

Lo más confuso es machdep.cpu.logical_per_package: 16 . Lo único que se me ocurre es que, de algún modo, el número de hyperthreads por núcleo se multiplicó por error por el número de núcleos por paquete.

Esas son mis suposiciones, pero me gustaría saberlo: ¿A qué se refieren exactamente estas variables?

3voto

rybosome Puntos 1829

tl;dr: Este es el comportamiento correcto, tal y como lo diseñó Intel.


Detalles:

machdep.cpu.logical_per_package se implementa en el núcleo en bsd/dev/i386/sysctl.c :

static int
cpu_logical_per_package SYSCTL_HANDLER_ARGS
{
    __unused struct sysctl_oid *unused_oidp = oidp;
    __unused void *unused_arg1 = arg1;
    __unused int unused_arg2 = arg2;
    i386_cpu_info_t *cpu_info = cpuid_info();

    if (!(cpuid_features() & CPUID_FEATURE_HTT)) {
        return ENOENT;
    }

    return SYSCTL_OUT(req, &cpu_info->cpuid_logical_per_package,
               sizeof(cpu_info->cpuid_logical_per_package));
}

Este sysctl devuelve el cpuid_logical_per_package campo del cpu_info estructura. Para ver cómo se rellena ese campo, examinamos osfmk/i386/cpuid.c :

static void
cpuid_set_generic_info(i386_cpu_info_t *info_p)
{

...

    cpuid_fn(1, reg);

...

    if (info_p->cpuid_features & CPUID_FEATURE_HTT) {
        info_p->cpuid_logical_per_package =
            bitfield32(reg[ebx], 23, 16);
    } else {
        info_p->cpuid_logical_per_package = 1;
    }

...

}

La primera parte de esta función ejecuta el programa Intel x86 CPUID con un valor de operando de 1 que recopilará cierta información de la CPU y rellenará el archivo E[A,B,C,D]X se registra con él. Más adelante examinaremos los bits 16-23 de la EBX y guardarlas en el cpuid_logical_per_package campo.

Para comprender el significado de lo que se encontrará en ese campo de bits de EBX pasamos a la Manual del desarrollador de software Intel , Volumen 2A, capítulo 3, página 215 ( CPUID-Identificación de la CPU ) y busque la definición de registro para 1 opcode:

Table of CPUID operand 1 results in the E*X registers from Intel SDM Volume 2A, Chapter 3, Page 215 - CPUID

La parte que nos interesa dice:

Bits 23 - 16: Número máximo de ID direccionables para procesadores lógicos en este paquete físico *.

*- El entero de potencia de 2 más cercano que no sea menor que EBX[23:16] es el número de IDs APIC iniciales únicos reservados para el direccionamiento diferentes procesadores lógicos en un paquete físico. Este campo sólo es válido si CPUID.1.EDX.HTT[bit 28]= 1.

Así que lo que esto nos está diciendo es que el sysctl nombre del selector " cpu_logical_per_package " es un término equivocado . Te dice el rango válido de números ID que el controlador de interrupciones puede utilizar para identificar CPUs lógicas y esto hace no se corresponden necesariamente con el número de CPU lógicas que tiene en realidad.

La situación es análoga para machdep.cpu.cores_per_package que se genera en cpuid_set_cache_info() en el mismo osfmk/i386/cpuid.c archivo:

static void
cpuid_set_cache_info( i386_cpu_info_t * info_p )
{

...

    reg[eax] = 4;           /* cpuid request 4 */
    reg[ecx] = index;       /* index starting at 0 */
    cpuid(reg);

...

    info_p->cpuid_cores_per_package
            = bitfield32(reg[eax], 31, 26) + 1;

...

}

Y mirando el SDM :

Table of CPUID operand 4 results in the E*X registers from Intel SDM Volume 2A, Chapter 3, Page 216 - CPUID

Así que la moraleja es:

Debe confiar en machdep.cpu.core_count y .thread_count para determinar el número real de núcleos físicos y lógicos, respectivamente, y consideran que los otros dos campos sólo son útiles para los programadores que necesitan trabajar con el núcleo y tienen una necesidad específica de conocer el ID máximo direccionable para los procesadores lógicos y físicos.


Si aún se pregunta por qué un procesador lógico o físico puede tener un ID superior al número real de procesadores disponibles en el silicio, la razón es que es el resultado de la forma en que se fabrica el silicio. La fabricación de chips es un proceso enormemente caro y complejo, y cualquier reducción de la complejidad va a ahorrar millones de dólares. Resulta que es más barato fabricar un chip con ocho núcleos físicos grabados en la matriz y luego quemar unos cuantos fusibles internos programables una sola vez para desconectar cuatro de los núcleos físicos de ese circuito, que crear máscaras y herramientas específicas para una matriz de cuatro núcleos totalmente separada. Así que Intel fabrica un montón de chips de 8 núcleos y luego vende la versión amputada de 4 núcleos más barata.

Sin embargo, la mayor parte del resto del chip sigue pensando que tiene 8 núcleos. Cada subsistema de un procesador tiene un identificador único con el que el resto de subsistemas pueden identificarlo. 1 s y 0 s para representar un número decimal. Como estos ID están hechos de transistores, son partes inmutables de la máscara y no cambian aunque se fundan los fusibles OTP para desactivar la mitad de los núcleos. Por lo tanto, un chip original de 8 núcleos puede tener, por ejemplo, identificadores lógicos de núcleo que oscilen entre 0-15 pero la versión más barata de 4 núcleos sólo utiliza IDs 8-15 y la primera 0-7 no son realmente direccionables. Por lo tanto, el esquema de numeración puede ser mayor que el número real de núcleos disponibles. Espero que esto tenga sentido.

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X