Горячее подключение процессора и строгая многопоточность 1:1
Я хочу добавить поддержку горячего подключения процессора в моем приложении, которое имеет строгие правила соответствия. Каждое физическое ядро привязано ровно к одному потоку, но логика, которую я использую для прикрепления потока к процессору, довольно наивна и дает сбой, если процессор между 0..N находится в автономном режиме.
Я выбрал подход, где у меня есть массив размера MAX_CPU
где каждый процессор в системе отображается в слот по его идентификатору. Например, CPU0 -> threads[0]
и CPU1 -> threads[1]
, и так далее. Идея состоит в том, чтобы отразить настройки системы.
for (i = 0; i < N; ++i)
set_affinity(threads[i], i);
Однако, если автономный процессор встречается где-либо кроме конца, он потерпит неудачу.
Что еще хуже, когда процессор отключается во время выполнения, маска привязки закрепленного потока сбрасывается без уведомления.
В конечном итоге, я надеюсь поддерживать сложные настройки, такие как:
CPU0 CPU1 CPU2 CPU3
ONLINE OFFLINE ONLINE OFFLINE
Как я могу включить в свое приложение информацию об онлайн и автономных процессорах?
Я избегаю /proc
а также /sys
поскольку я заинтересован в портировании на другие платформы, в частности, на различные BSD:s. Я сейчас использую x86_64, поэтому cpuid
Инструкция может быть полезной.
1 ответ
Оказывается sched_getaffinity(2)
это здорово и лучше подходит для этого случая. cpu_set_t
это заполняет не обобщенная маска, как 0xffffffff...
это подразумевало бы расписание в любом месте, но на самом деле это подробная и актуальная маска каждого онлайн и разрешенного процессора. С использованием CPU_*
макросы, можно извлечь, сколько процессоров в сети и какие.
cpu_set_t set;
int i, n;
if (sched_getaffinity(0, sizeof(cpu_set_t), &set))
return;
n = CPU_COUNT(&set);
/* pin a thread to each online and permitted cpu */
for (i = 0; n; ++i)
if (CPU_ISSET(i, &set)) {
/* spawn a thread and pin it to cpu identified by 'i' ... */
--n;
}
Когда получено уведомление о событии горячей замены, звонок sched_getaffinity(2)
из не закрепленной темы даст нам обновленную маску.
Дополнительным преимуществом является осознание таких утилит, как taskset(1)
,
FreeBSD имеет cpuset_getaffinity(2)
системный вызов, который, вероятно, работает аналогичным образом. У меня нет доступа, чтобы попробовать это сейчас.