Как я могу получить номер ядра ЦП из приложения пользовательского пространства (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()
чтобы увидеть маску, которая была установлена ранее, и использовать ее как лучшую догадку в ядре, на котором вы выполняете.