Wie können Sie die Prozessornummer finden, auf der ein Thread läuft?

Lesezeit: 7 Minuten

Benutzeravatar von Patrick Niedzielski
Patrick Niedzielski

Ich habe einen Speicherheap-Manager, der den Heap basierend auf der Anzahl der Prozessoren im System in verschiedene Segmente unterteilt. Speicher kann nur auf der Partition zugewiesen werden, die zum Prozessor des aktuell ausgeführten Threads gehört. Dies wird dazu beitragen, dass verschiedene Prozessoren weiterlaufen können, selbst wenn zwei verschiedene Prozessoren gleichzeitig Speicher zuweisen möchten, zumindest glaube ich.

Ich habe die Funktion gefunden GetCurrentProcessorNumber() für Windows, dies funktioniert jedoch nur unter Windows Vista und höher. Gibt es eine Methode, die unter Windows XP funktioniert?

Kann dies auch mit pthreads auf einem POSIX-System erfolgen?

  • Ist Ihnen bewusst, dass die meisten Betriebssysteme im Laufe der Zeit denselben Thread auf verschiedenen Kernen planen?

    – PlasmaHH

    30. April 2012 um 14:42 Uhr

Aus Ausgabe von man sched_getcpu:

NAME
       sched_getcpu - determine CPU on which the calling thread is running

SYNOPSIS
       #define _GNU_SOURCE
       #include <utmpx.h>

       int sched_getcpu(void);

DESCRIPTION
   sched_getcpu() returns the number of the CPU
   on which the calling thread is currently executing.

RETURN VALUE
   On success, sched_getcpu() returns a non-negative CPU number.
   On error, -1 is returned and errno is set to indicate the error.

SEE ALSO
   getcpu(2)

Leider ist dies Linux-spezifisch. Ich bezweifle, dass es eine tragbare Möglichkeit gibt, dies zu tun.

  • Eine schnelle Durchsicht der pthread-Dokumentation offenbart keine Aufrufe, die Teil der phtread-API sind, die dies tun.

    – Allmächtig

    6. Februar 2010 um 23:11 Uhr

  • Danke Ilia. Obwohl dies nur unter Linux funktioniert, ist es ein schöner und sauberer Funktionsaufruf. Wenn ich auf einen anderen Kernel portieren muss, kann ich diesen Funktionsaufruf einfach in eine modifizierte Version des obigen Assemblers ändern.

    – Patrick Niedzielski

    6. Februar 2010 um 23:17 Uhr

Für XP ergab ein schnelles Google Folgendes:

https://www.cs.tcd.ie/Jeremy.Jones/GetCurrentProcessorNumberXP.htm Hilft das?

  • Ja Dankeschön. Dies scheint sowohl unter Linux als auch unter Windows zu funktionieren, solange es auf einer x86-Plattform ausgeführt wird.

    – Patrick Niedzielski

    6. Februar 2010 um 23:02 Uhr

  • @Patrick Ich glaube nicht, dass das unter Linux funktioniert, sowieso nur XP in dieser Form.

    Benutzer257111

    6. Februar 2010 um 23:05 Uhr


  • Die Assemblersprache selbst ist nicht von den Betriebssystemen abhängig. Was den Unterschied zwischen _asm betrifft, __asm__asm usw. auf verschiedenen Plattformen und Compilern, mit denen ich umgehen kann.

    – Patrick Niedzielski

    6. Februar 2010 um 23:08 Uhr


  • @Patrick Ok ja, habe es gerade in den Assembly-Dokumenten nachgeschlagen, es ist eine tatsächliche Anweisung, kein API-Aufruf wie ein erster Gedanke … funktioniert für mich auch unter x86-64 Linux gut!

    Benutzer257111

    6. Februar 2010 um 23:40 Uhr

Zusätzlich zu Antony Vennards Antwort und dem Code auf der zitierten Seite ist hier Code, der auch für Visual C++ x64 funktioniert (kein Inline-Assembler):

DWORD GetCurrentProcessorNumberXP() {
   int CPUInfo[4];   
   __cpuid(CPUInfo, 1);
   // CPUInfo[1] is EBX, bits 24-31 are APIC ID
   if ((CPUInfo[3] & (1 << 9)) == 0) return -1;  // no APIC on chip
   return (unsigned)CPUInfo[1] >> 24;
}

Ein kurzer Blick auf die Implementierung von GetCurrentProcessorNumber() auf Win7 x64 zeigt, dass sie einen anderen Mechanismus verwenden, um die Prozessornummer zu erhalten, aber in meinen (wenigen) Tests waren die Ergebnisse für meine selbstgebaute und die offizielle Funktion gleich.

  • Cpuid ist eine serialisierende und extrem teure Anweisung (denken Sie an 1000 Zyklen). Sicherlich keine geeignete Wahl für den hier diskutierten Zweck. Es wäre besser, einen Haufen zufällig auszuwählen, vorausgesetzt, Sie verbringen nicht 1000 Zyklen im Zahlengenerator 🙂

    – Axel Rietschin

    2. April 2017 um 5:09 Uhr

Wenn Sie nur Konflikte vermeiden möchten, müssen Sie die aktuelle CPU nicht kennen. Sie könnten einfach zufällig einen Haufen auswählen. Oder Sie könnten einen Haufen pro Thread haben. Obwohl Sie auf diese Weise mehr oder weniger Konflikte bekommen, würden Sie den Overhead des Abfragens der aktuellen CPU vermeiden, der erheblich sein kann oder auch nicht. Sehen Sie sich auch den Scalable_allocator des Intel Thread Building Blocks an, der dieses Problem möglicherweise bereits besser gelöst hat, als Sie es wollen.

Dieses Design riecht schlecht für mich. Sie scheinen davon auszugehen, dass ein Thread einer bestimmten CPU zugeordnet bleibt. Das ist nicht garantiert. Ja, ein Thread kann normalerweise auf einer einzelnen CPU bleiben, muss es aber nicht, und schließlich wird Ihr Programm einen Thread haben, der die CPUs wechselt. Es passiert vielleicht nicht oft, aber irgendwann wird es passieren. Wenn Ihr Design dies nicht berücksichtigt, werden Sie höchstwahrscheinlich irgendwann auf einen schwer nachvollziehbaren Fehler stoßen.

Lassen Sie mich diese Frage stellen: Was passiert, wenn Speicher auf einer CPU zugewiesen und auf einer anderen freigegeben wird? Wie wird Ihr Haufen damit umgehen?

  • Der freigebende Prozessor spielt keine Rolle. In jedem Block speichere ich einen Zeiger auf die richtige Partition. Ich rufe die Funktion nur einmal pro Zuweisung auf, das ist also kein Problem. Es stimmt zwar, dass der aktuelle Thread Prozessoren ändern kann, aber dies würde auch zu keinen Problemen mit meinem Design führen (theoretisch: P). Der Haufen selbst ist immer noch ein verschlossener Haufen. Wenn also zwei verschiedene Threads dieselbe Partition zuweisen möchten, wird einer gesperrt, bis der andere fertig ist. Dieses Design minimiert lediglich die Wahrscheinlichkeit, dass ein Prozessor die Ausführung eines anderen sperrt.

    – Patrick Niedzielski

    7. Februar 2010 um 0:55 Uhr

  • Das Problem ist vermutlich, dass ein Thread möglicherweise migriert während Speicher zuweisen. Dies kann dazu führen, dass ein Thread feststellt, dass er auf CPU Nr. 0 läuft, einen Zeiger auf Heap Nr. 0 erhält, dann zu CPU Nr. 1 migriert und dann versucht, von Heap Nr. 0 zuzuordnen.

    – MSalter

    8. Februar 2010 um 11:02 Uhr

  • Das ist gut. Mein Heap ist selbst ein gesperrter Heap, also würde es auch ohne diese schwarze Magie der Prozessornummer gut funktionieren. Ich optimiere es, um andere Prozessoren, die nützlicher sein könnten, nicht auszusperren. In dem Fall, auf den Sie beide hingewiesen haben, wird ein anderer Prozessor für die Zuweisung gesperrt. Der Hauptpunkt meines Entwurfs ist jedoch, dass dies eher unwahrscheinlich ist und sich daher der Aufwand lohnt.

    – Patrick Niedzielski

    14. August 2010 um 14:42 Uhr

  • Das Design ist völlig in Ordnung, es muss nur davon ausgegangen werden, dass der Speicher gemeinsam genutzt wird (dh über CAS darauf zugreift), während er tatsächlich fast immer exklusiv wäre. Daher keine gemeinsamen Schreibvorgänge – und der Algorithmus skaliert perfekt.

    – bestes

    15. Juni 2014 um 10:55 Uhr

  • Der freigebende Prozessor spielt keine Rolle. In jedem Block speichere ich einen Zeiger auf die richtige Partition. Ich rufe die Funktion nur einmal pro Zuweisung auf, das ist also kein Problem. Es stimmt zwar, dass der aktuelle Thread Prozessoren ändern kann, aber dies würde auch zu keinen Problemen mit meinem Design führen (theoretisch: P). Der Haufen selbst ist immer noch ein verschlossener Haufen. Wenn also zwei verschiedene Threads dieselbe Partition zuweisen möchten, wird einer gesperrt, bis der andere fertig ist. Dieses Design minimiert lediglich die Wahrscheinlichkeit, dass ein Prozessor die Ausführung eines anderen sperrt.

    – Patrick Niedzielski

    7. Februar 2010 um 0:55 Uhr

  • Das Problem ist vermutlich, dass ein Thread möglicherweise migriert während Speicher zuweisen. Dies kann dazu führen, dass ein Thread feststellt, dass er auf CPU Nr. 0 läuft, einen Zeiger auf Heap Nr. 0 erhält, dann zu CPU Nr. 1 migriert und dann versucht, von Heap Nr. 0 zuzuordnen.

    – MSalter

    8. Februar 2010 um 11:02 Uhr

  • Das ist gut. Mein Heap ist selbst ein gesperrter Heap, also würde es auch ohne diese schwarze Magie der Prozessornummer gut funktionieren. Ich optimiere es, um andere Prozessoren, die nützlicher sein könnten, nicht auszusperren. In dem Fall, auf den Sie beide hingewiesen haben, wird ein anderer Prozessor für die Zuweisung gesperrt. Der Hauptpunkt meines Entwurfs ist jedoch, dass dies eher unwahrscheinlich ist und sich daher der Aufwand lohnt.

    – Patrick Niedzielski

    14. August 2010 um 14:42 Uhr

  • Das Design ist völlig in Ordnung, es muss nur davon ausgegangen werden, dass der Speicher gemeinsam genutzt wird (dh über CAS darauf zugreift), während er tatsächlich fast immer exklusiv wäre. Daher keine gemeinsamen Schreibvorgänge – und der Algorithmus skaliert perfekt.

    – bestes

    15. Juni 2014 um 10:55 Uhr

1437240cookie-checkWie können Sie die Prozessornummer finden, auf der ein Thread läuft?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy