2010-04-01 6 views
16

Ich habe 4 Threads, und ich versuche Thread 1 auf CPU 1, Thread 2 auf CPU 2 usw. zu setzen, aber wenn ich meinen Code unten ausführen, Die Affinitätsmasken geben die korrekten Werte zurück, aber wenn ich ein sched_getcpu() für die Threads anführe, geben sie alle an, dass sie auf CPU 4 laufen.CPU-Affinitätsmasken (Putting Threads auf verschiedenen CPUs)

Jeder weiß, was mein Problem hier ist?

Vielen Dank im Voraus!

#define _GNU_SOURCE 
#include <stdio.h> 
#include <pthread.h> 
#include <stdlib.h> 
#include <sched.h> 
#include <errno.h> 

void *pthread_Message(char *message) 
{ 
    printf("%s is running on CPU %d\n", message, sched_getcpu()); 
} 

int main() 
{ 
    pthread_t thread1, thread2, thread3, thread4; 
    pthread_t threadArray[4]; 
    cpu_set_t cpu1, cpu2, cpu3, cpu4; 
    char *thread1Msg = "Thread 1"; 
    char *thread2Msg = "Thread 2"; 
    char *thread3Msg = "Thread 3"; 
    char *thread4Msg = "Thread 4"; 
    int thread1Create, thread2Create, thread3Create, thread4Create, i, temp; 

    CPU_ZERO(&cpu1); 
    CPU_SET(1, &cpu1); 
    temp = pthread_setaffinity_np(thread1, sizeof(cpu_set_t), &cpu1); 
    printf("Set returned by pthread_getaffinity_np() contained:\n"); 
    for (i = 0; i < CPU_SETSIZE; i++) 
     if (CPU_ISSET(i, &cpu1)) 
      printf("CPU1: CPU %d\n", i); 

    CPU_ZERO(&cpu2); 
    CPU_SET(2, &cpu2); 
    temp = pthread_setaffinity_np(thread2, sizeof(cpu_set_t), &cpu2); 
    for (i = 0; i < CPU_SETSIZE; i++) 
     if (CPU_ISSET(i, &cpu2)) 
      printf("CPU2: CPU %d\n", i); 

    CPU_ZERO(&cpu3); 
    CPU_SET(3, &cpu3); 
    temp = pthread_setaffinity_np(thread3, sizeof(cpu_set_t), &cpu3); 
    for (i = 0; i < CPU_SETSIZE; i++) 
     if (CPU_ISSET(i, &cpu3)) 
      printf("CPU3: CPU %d\n", i); 

    CPU_ZERO(&cpu4); 
    CPU_SET(4, &cpu4); 
    temp = pthread_setaffinity_np(thread4, sizeof(cpu_set_t), &cpu4); 
    for (i = 0; i < CPU_SETSIZE; i++) 
     if (CPU_ISSET(i, &cpu4)) 
      printf("CPU4: CPU %d\n", i); 

    thread1Create = pthread_create(&thread1, NULL, (void *)pthread_Message, thread1Msg); 
    thread2Create = pthread_create(&thread2, NULL, (void *)pthread_Message, thread2Msg); 
    thread3Create = pthread_create(&thread3, NULL, (void *)pthread_Message, thread3Msg); 
    thread4Create = pthread_create(&thread4, NULL, (void *)pthread_Message, thread4Msg); 

    pthread_join(thread1, NULL); 
    pthread_join(thread2, NULL); 
    pthread_join(thread3, NULL); 
    pthread_join(thread4, NULL); 

    return 0; 
} 

Antwort

16

Sie versuchen, die Affinität von Threads festzulegen, die Sie nicht initialisiert haben.

Edit: Ok, lassen Sie mich Ihnen ein paar mehr Infos:

nicht Thread-Handles Mischen Sie (das, was Sie in der pthread_t Variablen speichern) und was sie (a Ausführungs-Thread, der irgendwo läuft) darstellen. Sie haben versucht, eine Eigenschaft eines Threads vor dem Start mit einer API zu definieren, die das Thread-Objekt erfordert. Wie es passiert, pthread_create erstellt das Objekt und startet die Ausführung zur gleichen Zeit, so versuchen pthread_setaffinity_np ist nicht der richtige Weg zu gehen (das ist nützlich, wenn Sie Änderung der Affinität eines gerade laufenden Thread).

Aber ... pthread_create hat einen Attributparameter (Sie übergeben NULL an ihn). Dies speichert die Informationen darüber, wie der Thread erstellt werden soll.

Affinität ist eines der Attribute, die Sie über diesen Parameter festlegen können. Finden Sie in der man-Seite Dokumentation für pthread_attr_init und pthread_attr_setaffinity_np dafür, wie genau

+0

also muss ich sie zuerst pthread_create()? Aber das läuft schon die angegebene Funktion ... Ich bin mir nicht sicher, ob ich das ganze Konzept verstehe. Also sollte ich die Funktion sataffinity in meine Funktion pthread_Message() einfügen? – hahuang65

+0

Sie müssen den Thread nicht für sehr * lang * ausführen, d. H. Es könnte das erste sein, was der neu erstellte Thread tut. Dies würde bedeuten, dass es neu geplant wird, wenn die neue CPU-Maske ihre aktuelle CPU nicht enthält. – MarkR

+0

Ich verstehe immer noch nicht ... Ich möchte die Affinität Maske AFTER pthread_create(), während der Funktion, die pthread_create() aufruft, oder vor pthread_create()? – hahuang65

2

Ich denke, die am einfachsten, die CPU-Maske als Parameter für jeden Thread zu geben wäre und haben den Faden Anfrage gegeben Affinität selbst, wie im Beispiel hier: pthread_setaffinity_np(3).

+0

Woher weiß ich, welcher Thread (in meinem Fall thread1, thread2, thread3 oder thread4) pthread_self() aufruft? – hahuang65

+0

Ich denke, Bahbar hat das bereits beantwortet - benutze den thread function Parameter, der wirklich auf irgendwas zeigen könnte, sprich eine Struktur, die die Affinitätsmaske enthält, die der Thread für sich selbst anfordern würde. Seien Sie vorsichtig, wenn Sie nicht dieselbe Strukturinstanz zwischen Arbeitsthreads teilen. –

4

Hier ist, was Sie gesucht haben. Ich weiß, es ist eine späte Antwort, aber das könnte anderen helfen.

#include <stdio.h> 
#include <pthread.h> 
#include <stdlib.h> 
#include <sched.h> 
#include <errno.h> 

#include <unistd.h> 

int getNumberOfCpus(void) 
{ 
    long nprocs  = -1; 
    long nprocs_max = -1; 

    # ifdef _SC_NPROCESSORS_ONLN 
    nprocs = sysconf(_SC_NPROCESSORS_ONLN); 
    if (nprocs < 1) 
    { 
     //std::cout << "Could not determine number of CPUs on line. Error is " << strerror(errno) << std::endl; 
     return 0; 
    } 

    nprocs_max = sysconf(_SC_NPROCESSORS_CONF); 

    if (nprocs_max < 1) 
    { 
     //std::cout << "Could not determine number of CPUs in host. Error is " << strerror(errno) << std::endl; 
     return 0; 
    } 

    //std::cout << nprocs < " of " << nprocs_max << " online" << std::endl; 
    return nprocs; 

#else 
    //std::cout << "Could not determine number of CPUs" << std::endl; 
    return 0; 
#endif 
} 

void *pthread_Message(void *ptr) 
{ 
    sleep(10); 
    char *message; 
    message = (char *) ptr; 
    printf("%s \n", message); 
    cpu_set_t  l_cpuSet; 
    int   l_maxCpus; 
    int   j; 
    unsigned long l_cpuBitMask; 

    CPU_ZERO(&l_cpuSet); 
    printf("get affinity %d\n",pthread_getaffinity_np(pthread_self() , sizeof(cpu_set_t), &l_cpuSet)); 
    // printf("cpuset %d\n",l_cpuSet); 
    printf (" thread id %u\n", pthread_self());  

    if (pthread_getaffinity_np(pthread_self() , sizeof(cpu_set_t), &l_cpuSet) == 0) 
     for (int i = 0; i < 4; i++) 
      if (CPU_ISSET(i, &l_cpuSet)) 
       printf("XXXCPU: CPU %d\n", i); 
    for (long i=0; i< 10000000000; ++i); 
} 

int main() 
{ 
    pthread_t thread1, thread2, thread3, thread4; 
    pthread_t threadArray[4]; 
    cpu_set_t cpu1, cpu2, cpu3, cpu4; 
    const char *thread1Msg = "Thread 1"; 
    const char *thread2Msg = "Thread 2"; 
    const char *thread3Msg = "Thread 3"; 
    const char *thread4Msg = "Thread 4"; 
    int thread1Create, thread2Create, thread3Create, thread4Create, i, temp; 

    thread1Create = pthread_create(&thread1, NULL, &pthread_Message, (void*)thread1Msg); 
    sleep(1); 
    thread2Create = pthread_create(&thread2, NULL, &pthread_Message, (void*)thread2Msg); 
    sleep(1); 
    thread3Create = pthread_create(&thread3, NULL, &pthread_Message, (void*)thread3Msg); 
    sleep(1); 
    thread4Create = pthread_create(&thread4, NULL, &pthread_Message, (void*)thread4Msg); 


    CPU_ZERO(&cpu1); 
    CPU_SET(0, &cpu1); 
    temp = pthread_setaffinity_np(thread1, sizeof(cpu_set_t), &cpu1); 
    printf("setaffinity=%d\n", temp); 
    printf("Set returned by pthread_getaffinity_np() contained:\n"); 
    for (i = 0; i < CPU_SETSIZE; i++) 
     if (CPU_ISSET(i, &cpu1)) 
      printf("CPU1: CPU %d\n", i); 

    CPU_ZERO(&cpu2); 
    CPU_SET(1, &cpu2); 
    temp = pthread_setaffinity_np(thread2, sizeof(cpu_set_t), &cpu2); 
    for (i = 0; i < CPU_SETSIZE; i++) 
     if (CPU_ISSET(i, &cpu2)) 
      printf("CPU2: CPU %d\n", i); 

    CPU_ZERO(&cpu3); 
    CPU_SET(2, &cpu3); 
    temp = pthread_setaffinity_np(thread3, sizeof(cpu_set_t), &cpu3); 
    for (i = 0; i < CPU_SETSIZE; i++) 
     if (CPU_ISSET(i, &cpu3)) 
      printf("CPU3: CPU %d\n", i); 

    CPU_ZERO(&cpu4); 
    CPU_SET(3, &cpu4); 
    temp = pthread_setaffinity_np(thread4, sizeof(cpu_set_t), &cpu4); 
    for (i = 0; i < CPU_SETSIZE; i++) 
     if (CPU_ISSET(i, &cpu4)) 
      printf("CPU4: CPU %d\n", i); 

    // pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpu1); 



    // pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpu1); 

    pthread_join(thread1, NULL); 
    pthread_join(thread2, NULL); 
    pthread_join(thread3, NULL); 
    pthread_join(thread4, NULL); 

    return 0; 
}