我有一个C#项目,我必须访问处理器的当前工作负载,并确保在处理器的每个内核上运行一些特定的代码。我的问题是,访问我的处理器的工作负载似乎阻止我正确分配线程关联掩码。我在这里有一些代码,说明了问题:
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调用必须与线程关联掩码进行交互在某种程度上,如果它是从每个内核聚合一个性能计数,但我无法理解,为什么它应该影响以后对线程关联掩码的更改。有没有人对此问题有解释或解决方法?
答案 0 :(得分:1)
这是some other guy with same problem
似乎是微软未解决的问题。
以下是问题陈述 - 性能计数器更改线程的亲和力。 Microsoft support
他们建议调用SetThreadAffinity。 )显然,他们的解决方案不起作用。