加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 为什么NextValue调用performanceCounter会改变线程关联掩

发布时间:2020-12-15 21:09:39 所属栏目:百科 来源:网络整理
导读:我有一个C#项目,我必须访问我的处理器的当前工作负载,并确保我在处理器的每个内核上运行一些特定的代码.我的问题是,访问我的处理器的工作负载似乎阻止我正确分配线程关联掩码.我在这里有一些代码,说明了问题: using System;using System.Collections.Generi
我有一个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调用必须以某种方式与线程关联掩码交互,如果它是从每个内核聚合一个性能计数,但我无法理解,为什么它应该影响对线程关联掩码的未来更改.有没有人对此问题有解释或解决方法?

解决方法

这是 some other guy with same problem

似乎是Microsoft未解决的问题.

以下是问题陈述 – 性能计数器更改线程的亲和力. Microsoft support.

他们建议调用SetThreadAffinity. )显然,他们的解决方案是行不通的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读