2016-05-09 12 views
3

Ich habe eine virtuelle Maschine in Google Cloud mit 1 CPU-Sockel mit 16 Kernen und 2 Threads pro Kern (Hyper-Threading).sched_getcpu funktioniert nicht

Dies ist die Ausgabe von lscpu:

Architecture:   x86_64 
CPU op-mode(s):  32-bit, 64-bit 
Byte Order:   Little Endian 
CPU(s):    32 
On-line CPU(s) list: 0-31 
Thread(s) per core: 2 
Core(s) per socket: 16 
Socket(s):    1 
NUMA node(s):   1 
Vendor ID:    GenuineIntel 
CPU family:   6 
Model:     63 
Stepping:    0 
CPU MHz:    2300.000 
BogoMIPS:    4600.00 
Hypervisor vendor:  KVM 
Virtualization type: full 
L1d cache:    32K 
L1i cache:    32K 
L2 cache:    256K 
L3 cache:    46080K 
NUMA node0 CPU(s):  0-31 

ich es meinen Prozess renne und ich versuche, meine Fäden zwischen den verschiedenen logischen CPUs zu verteilen.

unsigned num_cpus = std::thread::hardware_concurrency(); 
LOG(INFO) << "Going to assign threads to " << num_cpus << " logical cpus"; 
cpu_set_t cpuset; 
int rc = 0; 
for (int i = 0; i < num_cpus - 5; i++) { 
    worker_threads.push_back(std::thread(&CalculationWorker::work, &(workers[i]), i)); 
    // Create a cpu_set_t object representing a set of CPUs. Clear it and mark 
    // only CPU i as set. 
    CPU_ZERO(&cpuset); 
    CPU_SET(i, &cpuset); 
    int rc = pthread_setaffinity_np(worker_threads[i].native_handle(), 
      sizeof(cpu_set_t), &cpuset); 
    if (rc != 0) { 
     LOG(ERROR) << "Error calling pthread_setaffinity_np: " << rc << "\n"; 
    } 
    LOG(INFO) << "Set affinity for worker " << i << " to " << i; 
} 

Die Sache ist, dass in der Tat num_cpus 32 ist, aber wenn ich die folgende Code-Zeile in jedem des laufenden Threads:

LOG(INFO) << "Worker thread " << worker_number << " on CPU " << sched_getcpu(); 

sched_getcpu() liefert 0 für alle Threads.
Hat es etwas damit zu tun, dass dies eine virtuelle Maschine ist?

UPDATE:
Ich fand heraus, dass pthread_setaffinity_np funktioniert, anscheinend gibt einige Daemon-Prozess sere im Hintergrund laufen, deshalb sah ich die anderen Kerne verwendet werden.
aber, sched_getcpu funktioniert immer noch nicht und gibt 0 auf alle Threads zurück, obwohl ich deutlich sehen kann, dass sie auf verschiedenen Kernen laufen.

+0

Sind Sie sicher, dass der Aufruf von 'sched_getcpu()' in jedem Thread nach dem Aufruf von 'pthread_setaffinity_np()' ausgeführt wird? – jotik

+0

@jotik Positiv. Außerdem kann ich sehen, dass die Funktion 'pthread_setaffinity_np' nicht wirklich etwas bewirkt, wenn ich die Affinität aller Threads zu einem einzigen Kern festlege, laufen die Threads immer noch auf verschiedenen Kernen. – eladm26

Antwort

1

Können Sie diese kleineren Programm auf der virtuellen Maschine versuchen laufen:

#include <iostream> 
#include <thread> 
using namespace std; 

int main(int argc, char *argv[]) 
{ 
    int rc, i; 
    cpu_set_t cpuset; 
    pthread_t thread; 

    thread = pthread_self(); 

    //Check no. of cores on the machine 
    cout << thread::hardware_concurrency() << endl; 

    /* Set affinity mask */ 
    CPU_ZERO(&cpuset); 
    for (i = 0; i < 8; i++) //I have 4 cores with 2 threads per core so running it for 8 times, modify it according to your lscpu o/p 
     CPU_SET(i, &cpuset); 

    rc = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset); 
    if (rc != 0) 
    cout << "Error calling pthread_setaffinity_np !!! "; 

    /* Assign affinity mask to the thread */ 
    rc = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset); 
    if (rc != 0) 
    cout << "Error calling pthread_getaffinity_np !!!"; 

    cout << "pthread_getaffinity_np() returns:\n"; 
    for (i = 0; i < CPU_SETSIZE; i++) 
    { 
     if (CPU_ISSET(i, &cpuset)) 
      { 
      cout << " CPU " << i << endl; 
      cout << "This program (main thread) is on CPU " << sched_getcpu() << endl; 
     } 
    } 
    return 0; 
} 

Dies wird Ihnen eine Idee geben, wenn pthread_setaffinity_np funktioniert oder nicht auf VM. Im Fall von VMs gibt es keine solche spezifische Einschränkung, stattdessen könnte dies auf einige Erzwingungen durch den Kernel in der Cloud für einen bestimmten Prozess zurückzuführen sein. Sie können mehr darüber lesen here.

Alternativ können Sie mit sched_setaffinity() überprüfen, ob Sie tatsächlich cpusets auf der VM setzen können.

Ich fand Ihren Kommentar (wenn ich die Affinität aller Threads zu einem einzigen Kern festlegen, laufen die Threads immer noch auf verschiedenen Kernen) und ursprüngliche Notiz (sched_getcpu() gibt 0 für alle Threads zurück) ein wenig verwirrend. Wahrscheinlich wird diese 0 für Ihren Haupt-Thread (Prozess) in allen Threads zurückgegeben.

+0

Als ich meine ursprüngliche Frage aktualisiert habe, funktioniert 'sched_setaffinity' zwar, aber' sched_getcpu' gibt 0 und alle Threads zurück. – eladm26