Запрос потока (не процесса) сродства процессора?
В 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();