Страница 1 из 1

Как прибить поток к ядру?

СообщениеДобавлено: 22.09.2016 22:11:36
CRobin
Здравствуйте. Использую функции SetThreadAffinityMask и аналогичной pthread_getaffinity_np. Не могу понять как составить маску ЦП (группы ЦП) для того чтоб задать соответствие? Под Windows стабильно результат ноль с кодом ошибки 6. Под Линукс формально удается что то засетить, но судя по тому что результат отличается от ожидаемого, получается угадать по форме, но не по сути. Рабочие примеры из интернетов весьма противоречивы, вероятно не подходят под новые архитектуры.

Re: Как прибить поток к ядру?

СообщениеДобавлено: 22.09.2016 23:40:54
Pavia
Наблюдал пару раз глюки. Код просто не срабатывал до перезагрузки компа.
А так ничего там сложного нет.
Каждый бит соответствует одному логическому-ядру. Если у вас 8 логических ядер. То соответственно вы должны выставлять не более 8 бит.

То что у майкрософт логические ядра, то у интела потоками.
К примеру у меня 1 ЦП имеющий 4 ядра(физических) и каждое ядро может исполнять одновременно по 2 два потока итого 8 логических ядер.
255 Д= 11111111 Б - т.е поток может исполняться на всех 8 логических ядрах.
254 Д = 11111110 Б - все кроме нуливого.

Если делаете под свой процесс, то разрешения прав не требуется. Если чужой то нужны права админа.

Добавлено спустя 3 минуты 41 секунду:
Забыл сказать что SetThreadAffinityMask - носит рекомендательный характер. И если ядро загружено по полной, то виндоус перераспределит принудительно на другое.

Re: Как прибить поток к ядру?

СообщениеДобавлено: 23.09.2016 00:53:44
скалогрыз
а ещё MSDN говорит, что назначать SetThreadAffinityMask нужно соответственно битам от GetProcessAffinityMask, а то ничё не получится.
A thread affinity mask must be a subset of the process affinity mask for the containing process of a thread. A thread can only run on the processors its process can run on. Therefore, the thread affinity mask cannot specify a 1 bit for a processor when the process affinity mask specifies a 0 bit for that processor

как то так:
Код: Выделить всё
program project1;

{$mode delphi}{$H+}

uses
  Windows, Classes, SysUtils;

var
  pm, sm : DWORD;
  l   : DWORD;
  res  : DWORD;
begin
  GetProcessAffinityMask( GetCurrentProcess, pm, sm);
  writeln('Process Id:   ', GetCurrentProcessId );
  writeln('Process Mask: ', IntToHex(pm, 8));
  writeln('System  Mask: ', IntToHex(sm, 8));
  l:=1;
  while (l<>0) and (l and pm = 0) do l:=l shl 1;
  if l = 0 then begin
    writeln('epic fail... no processors?');
    Halt(1);
  end;
  res:=SetThreadAffinityMask( GetCurrentThread, l and pm); // Новая маска для потока AND маска для процесса
  if res=0 then
    writeln('Error! ', GetLastError)
  else begin
    writelN('Thread mask was: ', INtToHex(res,8));
    writelN('Thread mask new: ', IntToHex(l, 8));
  end;
end.

(у меня на Windows 10 работает без ошибок)

Сам никогда не пробовал... а для каких задач такой функционал нужен?

PS. двойное переключение Affinity маски
Код: Выделить всё
program project1;

{$mode delphi}{$H+}

uses
  Windows, Classes, SysUtils;

var
  pm, sm : DWORD;
  l   : DWORD;
  res  : DWORD;
begin
  GetProcessAffinityMask( GetCurrentProcess, pm, sm);
  writeln('Process Id:   ', GetCurrentProcessId );
  writeln('Process Mask: ', IntToHex(pm, 8));
  writeln('System  Mask: ', IntToHex(sm, 8));

  writeln('First try:');
  l:=1;
  while (l<>0) and (l and pm = 0) do l:=l shl 1;
  if l = 0 then begin
    writeln('epic fail... no processors?');
    Halt(1);
  end;
  res:=SetThreadAffinityMask( GetCurrentThread, l and pm); // Новая маска для потока AND маска для процесса
  if res=0 then
    writeln('Error! ', GetLastError)
  else begin
    writelN('Thread mask was: ', INtToHex(res,8));
    writelN('Thread mask new: ', IntToHex(l, 8));
  end;

  writeln('Second try:');
  l:=l shl 1;
  while (l<>0) and (l and pm = 0) do l:=l shl 1;
  if l = 0 then begin
    writeln('no more processors to play :(');
    Halt(1);
  end;
  res:=SetThreadAffinityMask( GetCurrentThread, l and pm);
  if res=0 then
    writeln('Error! ', GetLastError)
  else begin
    writelN('Thread mask was: ', INtToHex(res,8));
    writelN('Thread mask new: ', IntToHex(l, 8));
  end;
end.

(опять же, у меня на Windows 10 работает без ошибок)

Re: Как прибить поток к ядру?

СообщениеДобавлено: 23.09.2016 01:14:39
CRobin
Нашел одну из своих ошибок. скалогрыз функция не работает с GetCurrentThread так же как и с self.ThreadID, у меня завелось только с self.Handle (разные численные значения на Win7) вы знаете что это за сущности?

Re: Как прибить поток к ядру?

СообщениеДобавлено: 23.09.2016 01:24:30
скалогрыз
ThreadID это точно не Handle, который функция ожидает.
ID - это уникальный индентификатор потока/процесса на системном уровне. (все другие процессы/потоки его таким увидят)
А хендл уникален разве что внутри одного процесса, и должен использоваться для API вызовов.

Курить (совсем чуток) здесь

я думаю у тебя заработал с GetCurrentThread (т.к. в моём коде работает), может быть ты вызвал GetCurrentThreadID?

Опять же, ты киваешь в сторону Self.Handle, а значит ты используешь TThread. Вот бы код посмотреть :roll:

Re: Как прибить поток к ядру?

СообщениеДобавлено: 23.09.2016 01:40:34
CRobin
скалогрыз функция GetCurrentThread понимается как не объявлена, зато GetCurrentThreadID сразу возвращает айди треда. Так что вы правы, видимо я пытался использовать его. Используется класс TThread, со свойством Self.Handle все работает корретно, только что проверил.

Re: Как прибить поток к ядру?

СообщениеДобавлено: 23.09.2016 02:45:16
скалогрыз
CRobin писал(а):функция GetCurrentThread понимается как не объявлена

Понятно - модуль Windows не используется, а используется что-то своё.
Тогда действительно, использование Self.Handle это то, что тебе нужно.


а для каких задач такой функционал нужен?

Re: Как прибить поток к ядру?

СообщениеДобавлено: 23.09.2016 14:27:40
CRobin
скалогрыз это нужно для корретной работы таймера при измерении малых отрезков времени.

Re: Как прибить поток к ядру?

СообщениеДобавлено: 23.09.2016 20:39:21
скалогрыз
CRobin писал(а):скалогрыз это нужно для корретной работы таймера при измерении малых отрезков времени.
допустим

а performancecounter не справляется с задачей?

Re: Как прибить поток к ядру?

СообщениеДобавлено: 23.09.2016 22:34:52
CRobin
скалогрыз у меня кросплатформенное решение на основе RDTSC

Re: Как прибить поток к ядру?

СообщениеДобавлено: 24.09.2016 01:13:00
скалогрыз
CRobin писал(а):скалогрыз у меня кросплатформенное решение на основе RDTSC

тогда понятно зачем тебе affinity.
В линуксе с pthread_setaffinity_np заработал?

Re: Как прибить поток к ядру?

СообщениеДобавлено: 24.09.2016 02:40:51
CRobin
скалогрыз да, работает точно по тому же принципу