tiempo sistema real operativo nula multiusuario multitarea multiproceso monousuario funciones ejemplos multithreading delphi winapi delphi-7 multitasking

multithreading - real - Por qué los hilos mueren de hambre incluso en sistemas operativos multitarea preventivos(Windows 7)



sistema operativo multiusuario funciones (4)

La planificación por turnos es una estrategia obvia para un kernel. Sin embargo, esa no es la forma en que funciona el programador de Windows. Solía, en los días de Windows 9x, un programador que era muy capaz de dar a varias VMs el mismo tiempo. Pero no en la rama NT, iniciada por el grupo de Dave Cutler, la programación se basa exclusivamente en la prioridad .

Cualquier hilo que tenga la prioridad más alta obtiene la CPU. Hay otro trozo de código en Windows que juega con la prioridad de un subproceso, modificándolo desde la prioridad predeterminada que se obtiene cuando se crea el subproceso. Ese código es consciente de cosas como un hilo que posee una ventana que está en primer plano. O un hilo que está esperando un objeto de sincronización que recibió una señal. O los problemas de programación más extraños que intentan resolver un problema de inversión prioritaria. Dar aleatoriamente un hilo la oportunidad de ejecutar aunque no era su turno.

Enfócate primero en escribir un código sano. Comenzar cien hilos no es una cosa muy sensata. Está intentando consumir recursos que la máquina realmente no tiene disponibles, nadie tiene una máquina con cien núcleos. Todavía. Potencias de dos, primero consigue una máquina con 128 núcleos.

Escribí una aplicación Win32 (en Delphi-7, que es de 32 bits utilizando la clase TThread) para crear 100 subprocesos. Cada subproceso cuando se reanude continuamente (en un bucle) incrementará un contador de 64 bits asociado con el objeto de la secuencia (por lo que no se bloqueará ni compartirá datos).

Si deja que el sistema se ejecute durante 10 a 15 segundos y se detiene después de eso, debería ver aproximadamente los mismos recuentos en cada uno de los hilos. Pero lo que observé fue que 81 hilos corrían por debajo de 400 millones de bucles y los restantes bucles más de 950 millones de veces. El hilo más lento obtuvo solo 230 millones en comparación con los 2111 millones más rápidos.

Según MSDN, la multitarea preventiva está en el nivel de subproceso (no en el nivel de proceso), por lo que cada uno de mis subprocesos debería haber obtenido su porción de tiempo en forma de turno rotativo. ¿Qué me falta aquí y por qué esta discrepancia?

Edit1: configuración de la máquina: Intel i7 Quad Core 3.4GHz con hiper-threading activado (8 hilos activos a la vez). Ejecución de Windows-7 de 64 bits profesional (y la aplicación de prueba es de 32 bits)

Edit2 (código de subproceso): la aplicación de prueba se genera con la optimización activada y sin ninguna información de depuración. Ejecute la aplicación de prueba fuera de IDE.

type TMyThread = class(TThread) protected FCount: Int64; public constructor Create; procedure Execute; override; property Count: Int64 read FCount; end; { TMyThread } constructor TMyThread.Create; begin inherited Create(True); FCount := 0; end; procedure TMyThread.Execute; begin inherited; while not Terminated do begin Inc(FCount); end; end;


Windows 7 está diseñado para usuarios de la tierra. Cuando su primer thread quiere hacer el trabajo, el sistema operativo le da un segmento de tiempo. Usted, el usuario, acaba de comenzar, después de todo. En el momento en que el 50.º hilo en sucesión (del mismo proceso) quiere trabajar, los subprocesos de mayor prioridad (procesos en segundo plano controlados por Windows 7 mismo) intervienen. Esto sucede de tal manera que algunos hilos tienen más suerte .

Usted y yo realmente no queremos un sistema operativo personal que proporcione el tiempo de CPU en función de los caprichos de los procesos de usuario de la tierra. Me gustaría saber cómo lo manejó el servidor de 2008 R2. También puede jugar con la configuración de la pestaña Avanzado: "Elegir cómo asignar recursos de procesador".


He reproducido y confirmo tus resultados. Además, deshabilitar el aumento de prioridad de subproceso no cambia la distribución. GetThreadTimes informa que los hilos con valores más altos tomaron más UserTime y viceversa, mientras que KernelTime parece no tener correlación con los valores.

Thread 97: 1081,5928 Ke:0 Us:25116161 Thread 98: 1153,8029 Ke:0 Us:26988173 Thread 99: 704,6996 Ke:0 Us:16848108

Claramente, algunos hilos realmente funcionan más que otros.

No he graficado los resultados, pero supongo que lo que estamos viendo es una distribución Normal , lo que significa que los resultados dependen de una serie de factores, algunos que son aleatorios.

Intenté desactivar hyper-threading (esto alisó un poco los resultados), luego asigné a cada subproceso un único procesador físico (usando SetThreadAffinityMask ). En el segundo caso, los valores estaban mucho más cerca el uno del otro.

SetThreadAffinityMask(Self.Handle, 1 shl (FIndex mod 4));

Puedo entender cómo la ejecución de un sistema de subprocesos múltiples puede hacer que algunos subprocesos sean "desafortunados": están programados para competir con otros subprocesos en el mismo procesador físico y, debido a la "afinidad suave" con este núcleo virtual, se ejecutan. en él una y otra vez, anotando así más bajo que otros.

Pero en cuanto a por qué unir cada hilo a un núcleo fijo ayuda en un sistema no hiperhumedecido, no lo sé.

Probablemente haya otras cosas aleatorias involucradas, como la actividad en los núcleos por otros procesos. El hilo puede ser "desafortunado" si el hilo de otro proceso asociado con el mismo núcleo repentinamente se despierta y comienza a hacer un trabajo (relativamente) pesado.

Todo esto es adivinar sin embargo.


Algunos buenos razonamientos aquí ... pero hay algunas características a tener en cuenta. Windows está tratando de hacer Multitarea con software. Su hardware no es multitarea, está usando la potencia para hacer lo que haría un sistema procesado en paralelo. En Windows, da prioridad. en muchos sentidos ... y es confuso.

Déjame explicarlo de esta manera. Tengo un pequeño programa que mira mis núcleos para su uso. Cuando Windows se carga, uno pensaría que TODOS los núcleos se usarían. NOPE. A medida que Windows se carga, los otros núcleos comienzan a usarse. Entonces, uno pensaría que a medida que Windows se cargue acelerará la carga, ya que tiene acceso a los núcleos. no acelera. No utiliza los núcleos son velocidad COMPLETA para cargar más rápido. Incluso si Windows lanzó programas a 1 core CADA vez que estaban cargando y ejecutándose, ESPERA que terminen. Si utilizó TODOS los núcleos para procesar cada programa, usa el Software (aproximadamente 100 veces más lento que el hardware) para ensamblar las piezas en el otro extremo. Hace mucho tiempo, Intel quería cambiar el hardware a paralelo procesado, y MS dijo ''NO'' ya que su software no está diseñado para eso. AHORA intentan empujar el diseño de hardware basado en serie al punto N. Incluso después de que MS compró el software NT. Se han olvidado de usar gran parte de su diseño, recientemente. Es necesario que haya algunos cambios de hardware. Es necesario que haya cambios en el lenguaje de programación (MS creó el lenguaje de programación) y el Núcleo de Windows necesita ser diseñado nuevamente. Sin cambio. necesita regresar y comenzar desde cero. Buena suerte con eso. para decirte qué edad tiene esta idea de pensamiento ... VIVA La ''Amiga.