Запрос потока (не процесса) сродства процессора? - PullRequest
4 голосов
/ 06 июля 2011

В Windows вы можете вызвать SetProcessAffinityMask для процесса и SetThreadAffinityMask для потока.Однако Windows, похоже, предоставляет только GetProcessAffinityMask, а не похожий API для отдельных потоков процесса.

У меня есть многопоточная программа, которая связывает отдельные потоки с процессорами во время выполнения.При запуске я хотел бы (внешне) запросить, какие потоки запущены на каких процессорах, чтобы убедиться, что он работает правильно.Я написал небольшую утилиту командной строки, чтобы сделать это.Но я не могу найти средства для определения того, с каким процессором (ами) или ядром (ями) связан отдельный поток.

Это, очевидно, должно быть возможно;В Интернете я видел описания того, как утилита отладки adplus может показывать вывод, похожий на pstack, чтобы показать сходство потоков.А Process Explorer показывает вкладку Threads на многопроцессорных компьютерах, которая показывает «Идеальный процессор» потока.

Кто-нибудь знает, как запросить эту информацию?

Ответы [ 3 ]

6 голосов
/ 06 июля 2011

Вы можете сделать это двумя вызовами на SetThreadAffinityMask.Эта функция возвращает исходную маску сходства для переданного дескриптора потока.

Итак ... выполните один вызов с маской, которая устанавливает сходство с одним ЦП, а затем выполните второй вызов для восстановленияисходная маска.

Вот полный исходный код C / C ++, включая проверку ошибок:

DWORD GetThreadAffinityMask(HANDLE thread)
{
    DWORD mask = 1;
    DWORD old = 0;

    // try every CPU one by one until one works or none are left
    while(mask)
    {
        old = SetThreadAffinityMask(thread, mask);
        if(old)
        {   // this one worked
            SetThreadAffinityMask(thread, old); // restore original
            return old;
        }
        else
        {
            if(GetLastError() != ERROR_INVALID_PARAMETER)
                return 0; // fatal error, might as well throw an exception
        }
        mask <<= 1;
    }

    return 0;
}

Этот код проверяет один ЦП за раз, пока не сработает настройка (в данном случае мы сейчасзнать оригинальную маску!) или пока начальная 1 не будет сдвинута из DWORD.Если запрашивается процессор, который недоступен, функция завершается с ошибкой ERROR_INVALID_PARAMETER, и мы просто попробуем следующий.Обычно первый процессор просто работает, поэтому он достаточно эффективен.

Если функция завершается ошибкой с чем-либо, кроме ERROR_INVALID_PARAMETER, это означает, что у нас либо недостаточно прав доступа к дескриптору, либо к системе.возникают некоторые реальные проблемы, потому что он не может выполнить наш запрос.Поэтому продолжать в этом случае не имеет смысла.

5 голосов
/ 08 июля 2011

Вызовите NtQueryInformationThread, с ThreadBasicInformation :

typedef struct _THREAD_BASIC_INFORMATION
{
    NTSTATUS ExitStatus;
    PTEB TebBaseAddress;
    CLIENT_ID ClientId;
    ULONG_PTR AffinityMask;
    KPRIORITY Priority;
    LONG BasePriority;
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;

AFAIK, нет задокументированного способа получения сходства потоков.

0 голосов
/ 30 апреля 2015

более быстрый способ - вызвать GetCurrentProcessorNumber см. msdn , который вернет номер процессора, на котором текущий поток работал во время вызова этой функции.

c # code:

/// <summary>
/// Retrieves the number of the processor the current thread was running on <para/>
/// during the call to this function.
/// </summary>
/// <returns>The function returns the current processor number.</returns>
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern int GetCurrentProcessorNumber();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...