2012-09-08 3 views
7

(affichage de cette avec la réponse parce que je ne pouvais pas trouver une explication complète de la façon de le faire nulle part, donc je pensais que cela pourrait avoir une certaine valeur pour quelqu'un)Définir l'affinité du processeur de fil dans Microsoft .Net

Comment puis-je définir l'affinité du processeur d'un thread particulier dans Microsoft .Net? Réglage de l'affinité du processus est trivial par System.Diagnostics.Process.ProcessorAffinity, mais la classe System.Threading.Thread offre aucune fonctionnalité et .Net ne garantit pas un thread géré est lié à un thread particulier du système d'exploitation.

Répondre

25

La séparation entre la gestion et les fils du système d'exploitation remonte à .Net 2.0, et les plans de l'équipe SQL Server pour mettre en œuvre des fils .Net en utilisant des fibres. Cela ne s'est jamais réellement passé, alors même s'il n'y a aucune garantie qu'un thread géré fonctionnera toujours sur le même thread de système d'exploitation, en pratique, c'est toujours le cas pour tous les hôtes .Net actuels. Étant donné que cela n'a pas changé dans toutes les années depuis l'introduction de .Net 2.0, il est peu probable que cela change jamais.

Il est possible de renforcer notre confiance, même pour les futures versions de .Net en utilisant la méthode System.Threading.Thread.BeginThreadAffinity. Cela garantit que le thread géré restera sur le même thread de système d'exploitation (donc il ne fait rien sur l'hôte CLR par défaut, car cela est déjà vrai par défaut). Je suppose qu'il est toujours possible que d'autres threads gérés puissent partager le même thread de système d'exploitation, mais cela semble improbable et n'est certainement pas le cas dans tous les hôtes .Net actuels. .Net permet d'accéder aux threads du système d'exploitation natif à l'aide de la classe System.Diagnostics.ProcessThread. Cette classe permet de modifier l'affinité du processeur du thread à l'aide de la propriété ProcessorAffinity. Cependant, relier un thread managé particulier à son ProcessThread a été délibérément difficile.

La seule façon de le faire est à l'intérieur du fil lui-même. Utilisez la méthode System.AppDomain.GetCurrentThreadId (ou PInvoke la fonction GetCurrentThreadId si vous ne voulez pas appeler une méthode désapprouvée, bien que cela ne fonctionne pas avec Mono sur les systèmes d'exploitation autres que Windows). Cela peut ensuite correspondre à la propriété ProcessThread.Id.

Cela permet de définir l'affinité du processeur avec le code suivant du fil (être appelé à l'intérieur du fil):

/// <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); 
} 

Gardez à l'esprit que, si cela fonctionne sur les versions actuelles de .Net, théoriquement l'absence de garantie que les threads gérés sont liés aux threads du système d'exploitation pourrait casser ce code dans le futur. Cependant, je considère cela extrêmement improbable.

Questions connexes