2012-09-08 25 views
7

(Publicación de esto con la respuesta porque no podía encontrar una explicación completa de cómo hacer esto en cualquier lugar, así que pensé que podría tener algún valor para alguien)conjunto de procesadores hilo de afinidad en Microsoft .Net

¿Cómo puedo establecer la afinidad del procesador de un hilo en particular en Microsoft .Net? Establecer la afinidad del proceso es trivial a través de System.Diagnostics.Process.ProcessorAffinity, pero la clase System.Threading.Thread no ofrece tal funcionalidad y .Net no garantiza que un subproceso administrado esté vinculado a ninguna cadena de sistema operativo en particular.

Respuesta

25

La separación entre los hilos del sistema administrado y operativo se remonta a .Net 2.0, y los planes del equipo de SQL Server para implementar los hilos .Net utilizando fibras. Esto nunca fue realmente a ninguna parte, por lo que aunque no hay garantía de que un hilo administrado siempre se ejecute en el mismo hilo del sistema operativo, en la práctica, este es siempre el caso para todos los hosts .Net actuales. Dado que esto no ha cambiado en todos los años desde la introducción de .Net 2.0, es poco probable que esto cambie alguna vez.

Es posible reforzar nuestra confianza incluso para versiones futuras de .Net utilizando el método System.Threading.Thread.BeginThreadAffinity. Esto garantiza que el subproceso administrado permanecerá en el mismo subproceso del sistema operativo (por lo que no hace nada en el host CLR predeterminado, ya que eso ya es cierto de manera predeterminada). Supongo que todavía es posible que otros subprocesos administrados puedan compartir el mismo subproceso de sistema operativo, pero esto parece improbable y definitivamente no es el caso en ningún host .Net actual.

.Net proporciona la capacidad de acceder a subprocesos del sistema operativo nativo utilizando la clase System.Diagnostics.ProcessThread, y esta clase tiene la capacidad de cambiar la afinidad del procesador del subproceso con la propiedad ProcessorAffinity. Sin embargo, vincular un hilo gestionado particular a su ProcessThread se hizo deliberadamente difícil.

La única manera real de hacerlo es desde dentro del propio hilo. Use el método System.AppDomain.GetCurrentThreadId (o PInvoque la función GetCurrentThreadId si no desea llamar a un método obsoleto, aunque eso no funcionaría con Mono en sistemas operativos que no sean Windows). Esto puede coincidir con la propiedad ProcessThread.Id.

Esto hace que sea posible establecer la afinidad del procesador del hilo con el siguiente código (que se llamará desde el interior de la rosca):

/// <summary> 
/// Sets the processor affinity of the current thread. 
/// </summary> 
/// <param name="cpus">A list of CPU numbers. The values should be 
/// between 0 and <see cref="Environment.ProcessorCount"/>.</param> 
public static void SetThreadProcessorAffinity(params int[] cpus) 
{ 
    if(cpus == null) 
     throw new ArgumentNullException("cpus"); 
    if(cpus.Length == 0) 
     throw new ArgumentException("You must specify at least one CPU.", "cpus"); 

    // Supports up to 64 processors 
    long cpuMask = 0; 
    foreach(int cpu in cpus) 
    { 
     if(cpu < 0 || cpu >= Environment.ProcessorCount) 
      throw new ArgumentException("Invalid CPU number."); 

     cpuMask |= 1L << cpu; 
    } 

    // Ensure managed thread is linked to OS thread; does nothing on default host in current .Net versions 
    Thread.BeginThreadAffinity(); 

#pragma warning disable 618 
    // The call to BeginThreadAffinity guarantees stable results for GetCurrentThreadId, 
    // so we ignore the obsolete warning 
    int osThreadId = AppDomain.GetCurrentThreadId(); 
#pragma warning restore 618 

    // Find the ProcessThread for this thread. 
    ProcessThread thread = Process.GetCurrentProcess().Threads.Cast<ProcessThread>() 
           .Where(t => t.Id == osThreadId).Single(); 
    // Set the thread's processor affinity 
    thread.ProcessorAffinity = new IntPtr(cpuMask); 
} 

Tenga en cuenta que, si bien esto funciona en las versiones actuales de .Net, teóricamente la falta de una garantía de que los hilos gestionados estén ligados a los hilos del sistema operativo podría romper este código en el futuro. Sin embargo, considero esto extremadamente improbable.

Cuestiones relacionadas