Маски привязки к процессору (размещение потоков на разных процессорах) - PullRequest
17 голосов
/ 02 апреля 2010

У меня 4 потока, и я пытаюсь настроить поток 1 для работы на ЦП 1, поток 2 на ЦП 2 и т. Д. Однако, когда я запускаю свой код ниже, маски сходства возвращают правильные значения, но когда я выполняю sched_getcpu () для потоков, они все возвращают, что они работают на ЦП 4.

Кто-нибудь знает, в чем моя проблема?

Заранее спасибо!

#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;
}

Ответы [ 3 ]

16 голосов
/ 02 апреля 2010

Вы пытаетесь установить сходство потоков, которые вы не инициализировали.

Редактировать: Хорошо, позвольте мне дать вам больше информации:

Не смешивайте дескрипторы потоков (то, что вы храните в переменной pthread_t) и что они представляют (поток выполнения, который выполняется где-то). То, что вы пытались сделать, это установить свойство потока перед его запуском с помощью API, который требует объект потока. Когда это происходит, pthread_create создает объект и одновременно запускает выполнение, поэтому попытка использовать pthread_setaffinity_np - неправильный путь (это полезно, если вы хотите изменить сродство текущего объекта). бегущая нить).

Но ... pthread_create имеет параметр атрибута (вы передаете ему значение NULL). Здесь хранится информация о том, как вы хотите, чтобы поток был создан.

Сродство является одним из атрибутов, которые вы можете установить с помощью этого параметра. См. Справочную документацию для pthread_attr_init и pthread_attr_setaffinity_np, чтобы узнать, как именно

5 голосов
/ 06 января 2012

Вот то, что вы искали. Я знаю, что это поздний ответ, но это может помочь другим.

#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;
}
2 голосов
/ 02 апреля 2010

Я думаю, что самым простым было бы дать маску ЦП в качестве параметра каждому потоку и получить запрос на поток с указанием соответствия, как в примере здесь: pthread_setaffinity_np(3).

...