Запрос потока (не процесса) сродства процессора?

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

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

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

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

3 ответа

Решение

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

Вызовите 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 нет никакого документированного способа получить сходство потока.

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

код C#:

/// <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();
Другие вопросы по тегам