Как я могу получить номер ядра ЦП из приложения пользовательского пространства (Linux, C)?

Предположительно есть библиотека или простой asm-объект, который может получить номер текущего процессора, на котором я выполняю.

4 ответа

Решение

Использование sched_getcpu определить процессор, на котором работает вызывающий поток. Увидеть man getcpu (системный вызов) и man sched_getcpu (обертка библиотеки). Однако обратите внимание, что там написано:

Информация, помещаемая в cpu, гарантированно будет актуальной только во время вызова: если только привязка к ЦП не была исправлена ​​с помощью sched_setaffinity(2), ядро ​​может изменить ЦП в любое время. (Обычно этого не происходит, потому что планировщик пытается минимизировать перемещения между процессорами, чтобы держать кеши горячими, но это возможно.) Вызывающая сторона должна быть готова обработать ситуацию, когда процессор и узел больше не являются текущим процессором и узлом.

Вам нужно сделать что-то вроде:

  • Вызовите sched_getaffinity и определите биты процессора
  • Перебирайте процессоры, выполняя sched_setaffinity для каждого из них (я не уверен, что после sched_setaffinity вы гарантированно будете в процессоре или вам нужно явно уступить?)
  • Выполнить CPUID (инструкция asm)... есть способ получить уникальный идентификатор для каждого ядра из одного из его выходных данных (см. Документацию Intel). Я смутно помню, что это "APIC ID".
  • Создайте таблицу (std::map?) Из идентификаторов APIC к номеру ЦП, маске сходства или чему-то еще.
  • Если вы сделали это в своем основном потоке, не забудьте вернуть sched_setaffinity всем CPUS!

Теперь вы можете снова использовать CPUID и искать, какое ядро ​​вы используете.

Но я бы спросил, зачем тебе это делать; обычно вы хотите получить контроль через sched_setaffinity, а не выяснять, на каком ядре вы находитесь (и даже это довольно редкая вещь, которую нужно / нужно). (Вот почему я не знаю решающей детали того, что именно нужно извлечь из CPUID, извините!)

Обновление: только что узнал о sched_getcpu из ответа litb здесь. Намного лучше! (хотя мой Debian/etch libc слишком стар, чтобы иметь его).

Я ничего не знаю, чтобы получить ваш текущий основной идентификатор. При переносе задач / процессов на уровне ядра вам не будет гарантировано, что он останется постоянным в течение любого промежутка времени, если только вы не работали в какой-либо форме режима реального времени.

Если вы хотите быть на конкретном ядре, вы можете использовать это sched_setaffinity() функция или taskset Команда для запуска вашей программы. Я полагаю, что для работы им нужны повышенные разрешения. В вашей программе вы можете запустить sched_getaffinity() чтобы увидеть маску, которая была установлена ​​ранее, и использовать ее как лучшую догадку в ядре, на котором вы выполняете.

sysconf(_SC_NPROCESSORS_ONLN);
Другие вопросы по тегам