为什么系统监视器没有显示正确的CPU亲和力?

时间:2013-12-12 05:33:23

标签: linux multithreading pthreads

我已经搜索了关于CPU亲和力的问题/答案并阅读了结果,但我仍然无法让我的线程达到单个CPU。

我正在开发一个将在专用的Linux机器上运行的应用程序,所以我不关心其他进程,只关注我自己的进程。此应用程序当前生成一个pthread,然后主线程进入while循环以使用POSIX msg队列处理控制消息。这个while循环阻塞等待控制消息进入然后处理它。因此主线程非常简单且非关键。我的代码工作得很好,因为我可以发送这个应用程序消息,它将处理它们就好了。所有控制消息的大小都非常小,仅用于控制应用程序的功能,即只发送/接收少量控制消息。

在我进入while循环之前,我使用sched_getaffinity()来记录所有可用的CPU。然后我使用sched_setaffinity()将此进程设置为单个CPU。然后我再次调用sched_getaffinity()来检查它是否设置为仅在一个CPU上运行,它确实是正确的。

产生的单个pthread做了类似的事情。我在新创建的pthread中做的第一件事就是调用pthread_getaffinity_np()并检查可用的CPU,然后调用pthread_setaffinity_np()将其设置为不同的CPU,然后调用pthread_getaffinity_np()来检查它是否按照需要设置它确实是正确的。

这令人困惑。当我运行应用程序并在系统监视器中查看CPU历史记录时,我发现在没有所有这些设置关联性东西的情况下运行应用程序时没有区别。调度程序在此四核盒上的4个CPU中的每个CPU中仍然运行几秒钟。因此,调度程序似乎忽略了我的亲和力设置。

我是否错误地期望看到一些证据表明主线程和pthread实际上是在自己的单CPU中运行?或者我忘了做更多的事情让我按照我的意愿去做?

谢谢,

-Andres

1 个答案:

答案 0 :(得分:0)

你没有答案,我会尽力给你:一些部分帮助

假设您检查了pthread_setaffinity_np的返回值:

如何分配cpuset非常重要,在主线程中创建它。为了你想要的。它将传播到连续的线程。你检查了退货代码吗?

您实际获得的cpuset将是硬件可用的cpus和您定义的cpuset的交集。 下面的代码中的min.h是一个通用的构建包含文件。您必须定义_GNU_SOURCE - 请注意comment on the last line of the code. CPUSETCPUSETSIZE是宏。我想我把它们定义在其他地方,我不记得了。它们可能位于标准标题中。

#define _GNU_SOURCE
#include "min.h"
#include <pthread.h>


int
main(int argc, char **argv)
{
    int s, j;
    cpu_set_t cpuset;
    pthread_t tid=pthread_self();

    // Set affinity mask to include CPUs 0 & 1

    CPU_ZERO(&cpuset);
    for (j = 0; j < 2; j++)
        CPU_SET(j, &cpuset);

    s = pthread_setaffinity_np(tid, sizeof(cpu_set_t), &cpuset);
    if (s != 0)
    {
        fprintf(stderr, "%d ", s);
        perror(" pthread_setaffinity_np");
        exit(1);
     }
     // lets see what we really have in the actual affinity mask assigned our thread

    s = pthread_getaffinity_np(tid, sizeof(cpu_set_t), &cpuset);
    if (s != 0)
    {
        fprintf(stderr, "%d ", s);
        perror(" pthread_setaffinity_np");
        exit(1);
     }

    printf("my cpuset has:\n");
    for (j = 0; j < CPU_SETSIZE; j++)
        if (CPU_ISSET(j, &cpuset))
            printf("    CPU %d\n", j);
    // @Andres note: any pthread_create call from here on creates a thread with the identical
    // cpuset - you do not have to call it in every thread.
    return 0;
}