Come posso ottenere il numero di core della CPU da un’app nello spazio utente (Linux, C)?

Presumibilmente esiste una libreria o un semplice BLOB di asm che può ottenere il numero della CPU corrente su cui sto eseguendo.

Utilizzare sched_getcpu per determinare la CPU su cui è in esecuzione il thread chiamante. Vedere man getcpu (la chiamata di sistema) e man sched_getcpu (un wrapper di libreria). Tuttavia, nota ciò che dice:

Le informazioni inserite in cpu sono garantite per essere aggiornate al momento della chiamata: a meno che l’affinità della CPU non sia stata risolta usando sched_setaffinity (2), il kernel potrebbe cambiare la CPU in qualsiasi momento. (Normalmente ciò non accade perché lo scheduler cerca di minimizzare i movimenti tra le CPU per mantenere le cache calde, ma è ansible.) Il chiamante deve essere preparato a gestire la situazione quando CPU e nodo non sono più la CPU e il nodo correnti.

Devi fare qualcosa come:

  • Chiama sched_getaffinity e identifica i bit della CPU
  • Iterate sulle CPU, facendo sched_setaffinity a ciascuna di esse (non sono sicuro se dopo sched_setaffinity si abbia la certezza di essere nella CPU, o si debba rendere esplicitamente?)
  • Esegui CPUID (istruzioni asm) … c’è un modo per ottenere un ID per core unico da uno dei suoi output (vedi i documenti Intel ). Ricordo vagamente che è “l’APIC ID”.
  • Costruisci una tabella (una std :: map?) Dagli ID APIC a un numero di CPU o una maschera di affinità o qualcosa del genere.
  • Se lo hai fatto sul thread principale, non dimenticare di impostare sched_setaffinity su tutti i CPUS!

Ora puoi nuovamente CPUU ogni volta che è necessario e cercare il nucleo su cui ti trovi.

Ma vorrei sapere perché è necessario farlo; normalmente vuoi prendere il controllo tramite sched_setaffinity piuttosto che scoprire quale nucleo sei attivo (e anche questa è una cosa piuttosto rara da volere / bisogno). (Ecco perché non conosco il dettaglio cruciale di cosa estrarre esattamente CPUID, scusa!)

Aggiornamento: appena appreso su sched_getcpu dalla risposta di litb qui. Molto meglio! (il mio Debian / etch libc è troppo vecchio per averlo però).

Non so nulla per ottenere il tuo attuale ID di base. Con la migrazione del task / processo a livello di kernel, non ti saresti garantito che rimarrebbe costante per un certo periodo di tempo, a meno che non fossi in esecuzione in qualche forma di modalità in tempo reale.

Se si desidera essere su un nucleo specifico, è ansible utilizzare la funzione sched_setaffinity() o il comando taskset per avviare il programma. Credo che questi abbiano bisogno di autorizzazioni elevate per funzionare, comunque. Nel tuo programma, potresti quindi eseguire sched_getaffinity() per vedere la maschera che era stata impostata in precedenza e usarla come migliore ipotesi al centro su cui stai eseguendo.

 sysconf(_SC_NPROCESSORS_ONLN);