Горячее подключение процессора и строгая многопоточность 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) системный вызов, который, вероятно, работает аналогичным образом. У меня нет доступа, чтобы попробовать это сейчас.

Другие вопросы по тегам