Почему вызов NextValue для PerformanceCounter меняет маску сходства потоков - PullRequest
4 голосов
/ 19 августа 2010

У меня есть проект на 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 должен взаимодействовать с маской сходства потока в некотором смысле, если он агрегирует счетчик производительности для каждого ядра, но я не могу понять, почему это должно повлиять на будущие изменения маски соответствия потоков. У кого-нибудь есть объяснение или решение этой проблемы?

1 Ответ

1 голос
/ 26 июня 2011

Вот какой-то другой парень с такой же проблемой

Похоже, нерешенная проблема от Microsoft.

Вот формулировка проблемы - счетчики производительности изменяют сходствонить. Поддержка Microsoft .

Они предлагают вызывать SetThreadAffinity.) Очевидно, что их решение не работает.

...