【问题标题】:CPU Affinity Masks (Putting Threads on different CPUs)CPU Affinity Masks(将线程放在不同的 CPU 上)
【发布时间】:2011-02-03 12:59:22
【问题描述】:

我有 4 个线程,我正在尝试将线程 1 设置为在 CPU 1 上运行,将线程 2 设置为在 CPU 2 上运行,等等。 但是,当我在下面运行我的代码时,关联掩码返回正确的值,但是当我在线程上执行 sched_getcpu() 时,它们都返回它们正在 CPU 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;
}

【问题讨论】:

    标签: linux multithreading pthreads parallel-processing


    【解决方案1】:

    您正在尝试设置未初始化的线程的亲和性。

    编辑:好的,让我给你更多信息:

    不要混合线程句柄(存储在 pthread_t 变量中的东西)和它们所代表的东西(在某处运行的执行线程)。您尝试做的是在线程启动之前使用需要线程对象的 API 设置线程的属性。碰巧 pthread_create 创建对象并同时开始执行,因此尝试使用pthread_setaffinity_np 不是正确的方法(如果您想更改当前正在运行的线程)。

    但是...pthread_create 有一个属性参数(您将 NULL 传递给它)。这是存储您希望如何创建线程的信息。

    亲和力是您可以通过该参数设置的属性之一。具体方法请参见 pthread_attr_initpthread_attr_setaffinity_np 的手册页文档

    【讨论】:

    • 所以我必须先 pthread_create() 他们?但这已经运行了指定的功能......我不太确定我是否理解整个概念。所以我应该把 setaffinity 函数放在我的 pthread_Message() 函数中?
    • 您不需要将线程运行很长时间,即它可能是新创建的线程执行的第一件事。这意味着如果新的 cpu 掩码不包括其当前 cpu,它将被重新安排。
    • 我还是不明白...我想在 pthread_create() 之后、pthread_create() 调用的函数期间或 pthread_create() 之前设置关联掩码?
    • @hahuang65:我添加了更多信息,希望对您有所帮助。
    【解决方案2】:

    这就是您要查找的内容。我知道这是一个迟到的答案,但这可能对其他人有所帮助。

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

    【讨论】:

      【解决方案3】:

      我认为最简单的方法是将 CPU 掩码作为参数提供给每个线程,并让线程请求本身具有关联性,例如此处的示例:pthread_setaffinity_np(3)

      【讨论】:

      • 我如何知道哪个线程(在我的例子中是 thread1、thread2、thread3 或 thread4)正在调用 pthread_self()?
      • 我认为 Bahbar 已经回答了这个问题 - 使用线程函数参数,它可以真正指向任何东西,比如一个包含线程将为其自身请求的关联掩码的结构。请注意不要在工作线程之间共享相同的结构实例。
      猜你喜欢
      • 2016-09-07
      • 2014-12-08
      • 2012-10-10
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 2016-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多