4

我有一個C#項目,我必須同時訪問我的處理器的當前工作負載,並確保我在處理器的每個內核上運行一些特定的代碼。我的問題是,訪問我的處理器的工作負載似乎阻止我正確分配線程關聯掩碼。我有一些代碼在這裏,這說明了這個問題:爲什麼性能計數器的NextValue調用更改線程親和性掩碼

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

運行此代碼產生以下輸出:

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

因此,它似乎是cpuUsage.NextValue電話不知何故改變線程關聯掩碼,並且也不可能將掩碼更改爲1.確實有意義的是,如果Nextvalue調用將聚合每個內核的性能計數,那麼它必須以某種方式與線程關聯掩碼進行交互,但我無法理解,爲什麼它會影響對線程關聯掩碼的未來更改。有沒有人有解釋,或解決這個問題?

回答

1

這裏是some other guy with same problem

好像從微軟一個尚未解決的問題。

這是問題的表述 - 性能計數器更改線程的親和力。 Microsoft support

他們建議調用SetThreadAffinity。 )顯然,他們的解決方案不起作用。

相關問題