问题描述
我有一个C#项目,在这里我必须访问处理器的当前工作负载,并确保在处理器的每个内核上运行一些特定的代码.我的问题是,访问处理器的工作负载似乎阻止了我正确分配线程相似性掩码.我这里有一些代码可以说明问题:
I have a C# project, where I have to both access the current workload of my processor, and ensure, that I run some specific code on every kernel of the processor. My problem is, that accessing the workload of my processor seems to prevent me from correctly assigning a thread affinity mask. I have some code here, that illustrates the problem:
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;
}
}
}
运行此代码将产生以下输出:
Running this code yields the following output:
Pre: thread affinity: 3
Pre: all kernels accessible
Post: thread affinity: 2
Post: some kernels not accessible: 1
因此,似乎cpuUsage.NextValue调用以某种方式更改了线程亲和力掩码,并且也使得无法将掩码更改为1.确实有意义,Nextvalue调用将必须与线程亲和力掩码交互以某种方式,如果它正在汇总每个内核的性能计数,但我无法理解,为什么它会影响将来对线程相似性掩码的更改.是否有人对此问题有解释或解决方法?
So, it seems that the cpuUsage.NextValue call somehow changes the thread affinity mask, and also makes it impossible to change the mask to 1. It does make sense, that the Nextvalue call would have to interact with the thread affinity mask in some way, if it is aggregating a performance count from each kernel, but I cannot understand, why it should affect future changes to the thread affinity mask. Does anybody have an explanation, or a workaround to this problem?
推荐答案
此处为其他遇到相同问题的人
似乎是Microsoft尚未解决的问题.
Seems like an unsolved issue from Microsoft.
这是问题的陈述-性能计数器会更改线程的亲和力. Microsoft支持.
Here is statement of the problem - Performance Counters change the affinity of the thread. Microsoft support.
他们建议调用SetThreadAffinity. )显然,他们的解决方案无法正常工作.
They suggest calling to SetThreadAffinity. ) Obviously, their solution, is not working.
这篇关于为什么调用PerformanceCounter的NextValue更改线程亲和力掩码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!