4

J'ai un projet C#, où je dois à la fois accéder à la charge de travail actuelle de mon processeur et m'assurer que j'exécute du code spécifique sur chaque noyau du processeur. Mon problème est, qu'accéder à la charge de travail de mon processeur semble m'empêcher d'assigner correctement un masque d'affinité de fil. J'ai un code ici, qui illustre le problème:Pourquoi NextValue appelle-t-on performanceCounter?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Runtime.InteropServices; 
using System.Diagnostics; 

namespace KernelAffinitySpike 
{ 
    class Program 
    { 
     [DllImport("kernel32.dll", SetLastError = true)] 
     private static extern UIntPtr SetThreadAffinityMask(IntPtr hThread, UIntPtr dwThreadAffinityMask); 

     [DllImport("kernel32.dll", SetLastError = true)] 
     private static extern IntPtr GetCurrentThread(); 

     private static PerformanceCounter cpuUsage; 
     private static UIntPtr oldMask, newMask, testMask; // thread-level processor affinity masks. 

     static void Main(string[] args) 
     { 
      InitPerformanceCounter(); 

      Console.WriteLine("Pre: thread affinity: " + CurrentThreadAffinityMask()); 
      if (AllKernelsAccessible()) 
       Console.WriteLine("Pre: all kernels accessible"); 
      else 
      { 
       Console.Write("Pre: some kernels not accessible: "); 
       foreach (UInt32 kernel in InaccessibleKernels()) 
        Console.Write(kernel + " "); 
       Console.WriteLine(); 
      } 

      float load = cpuUsage.NextValue(); 

      Console.WriteLine("Post: thread affinity: " + CurrentThreadAffinityMask()); 
      if (AllKernelsAccessible()) 
       Console.WriteLine("Post: all kernels accessible"); 
      else 
      { 
       Console.Write("Post: some kernels not accessible: "); 
       foreach (UInt32 kernel in InaccessibleKernels()) 
        Console.Write(kernel + " "); 
       Console.WriteLine(); 
      } 

      Console.ReadLine(); 
     } 

     static void InitPerformanceCounter() 
     { 
      cpuUsage = new PerformanceCounter(); 
      cpuUsage.CategoryName = "Processor"; 
      cpuUsage.CounterName = "% Processor Time"; 
      cpuUsage.InstanceName = "_Total"; 
     } 

     static UInt32 CurrentThreadAffinityMask() 
     { 
      oldMask = SetThreadAffinityMask(GetCurrentThread(), (UIntPtr) 3); // 3 just enables all processors on a dual core. I'm only interested in the return value. 
      SetThreadAffinityMask(GetCurrentThread(), oldMask); 
      return (UInt32) oldMask; 
     } 

     static List<UInt32> InaccessibleKernels() 
     { 
      List<UInt32> inaccessible = new List<UInt32>(); 
      for (int i = 0; i < Environment.ProcessorCount; i++) 
      { 
       newMask = (UIntPtr)(1 << i); 
       oldMask = SetThreadAffinityMask(GetCurrentThread(), newMask); 
       testMask = SetThreadAffinityMask(GetCurrentThread(), oldMask); 
       if (newMask != testMask) 
        inaccessible.Add((UInt32) newMask); 
      } 
      return inaccessible; 
     } 

     static bool AllKernelsAccessible() 
     { 
      return InaccessibleKernels().Count == 0; 
     } 
    } 
} 

exécution de ce code donne le résultat suivant:

Pre: thread affinity: 3 
Pre: all kernels accessible 
Post: thread affinity: 2 
Post: some kernels not accessible: 1 

Ainsi, il semble que l'appel cpuUsage.NextValue change en quelque sorte le masque d'affinité de fil, et il est également impossible de changer le masque à 1. Il est logique que l'appel de Nextvalue doive interagir avec le masque d'affinité de thread d'une certaine manière, s'il agrège un compte de performance de chaque noyau, mais je ne peux pas comprendre, pourquoi cela devrait affecter les modifications futures du masque d'affinité des threads. Quelqu'un at-il une explication ou une solution à ce problème?

Répondre

1

est ici some other guy with same problem

On dirait un problème non résolu de Microsoft.

Voici l'énoncé du problème - Les compteurs de performance changent l'affinité du fil. Microsoft support.

Ils suggèrent d'appeler SetThreadAffinity.) De toute évidence, leur solution ne fonctionne pas.