2

我在 cent os 5.3 和 cent os 6.3 上编译以下代码:

#include <pthread.h>
#include <list>
#include <unistd.h>
#include <iostream>
using namespace std;
pthread_mutex_t _mutex;
pthread_spinlock_t spinlock;

list<int *> _task_list;

void * run(void*);
int main()
{
    int worker_num  = 3;
        pthread_t pids[worker_num];
        pthread_mutex_init(&_mutex, NULL);
        for (int worker_i = 0; worker_i < worker_num; ++worker_i)
        {
                pthread_create(&(pids[worker_i]), NULL, run, NULL);
        }
    sleep(14);
}


void *run(void * args)
{
        int *recved_info;
    long long start;
        while (true)
        {
            pthread_mutex_lock(&_mutex);
                if (_task_list.empty())
                {
                        recved_info = 0;
                }
                else
                {
                        recved_info = _task_list.front();
                        _task_list.pop_front();
                }
            pthread_mutex_unlock(&_mutex);

                if (recved_info == 0)
                {
                        int f = usleep(1);
            continue;
        }
    }
}

在 5.3 上运行时,您甚至找不到最上面的进程,cpu 使用率约为 0%。但是在 cent os 6.3 上,在 4 核 cpu 上有 6 个线程的情况下,它大约是 20%。

所以我用timestace检查了 a.out ,结果是这样的:

在 5.3 上:

real    0m14.003s
user    0m0.001s
sys     0m0.001s

在 6.3 上:

real    0m14.002s
user    0m1.484s
sys  0m1.160s

跟踪:

在 5.3 上:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 91.71    0.002997           0     14965           nanosleep
  8.29    0.000271         271         1           execve
  0.00    0.000000           0         5           read
  0.00    0.000000           0        10         4 open
  0.00    0.000000           0         6           close
  0.00    0.000000           0         4         4 stat
  0.00    0.000000           0         6           fstat
  0.00    0.000000           0        22           mmap
  0.00    0.000000           0        13           mprotect
  0.00    0.000000           0         1           munmap
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         3           rt_sigaction
  0.00    0.000000           0         3           rt_sigprocmask
  0.00    0.000000           0         1         1 access
  0.00    0.000000           0         3           clone
  0.00    0.000000           0         1           uname
  0.00    0.000000           0         1           getrlimit
  0.00    0.000000           0         1           arch_prctl
  0.00    0.000000           0        38         4 futex
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0         4           set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00    0.003268                 15092        13 total

在 6.3 上:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 99.99    1.372813          36     38219           nanosleep
  0.01    0.000104           0       409        43 futex
  0.00    0.000000           0         5           read
  0.00    0.000000           0         6           open
  0.00    0.000000           0         6           close
  0.00    0.000000           0         6           fstat
  0.00    0.000000           0        22           mmap
  0.00    0.000000           0        15           mprotect
  0.00    0.000000           0         1           munmap
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         3           rt_sigaction
  0.00    0.000000           0         3           rt_sigprocmask
  0.00    0.000000           0         7         7 access
  0.00    0.000000           0         3           clone
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1           getrlimit
  0.00    0.000000           0         1           arch_prctl
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0         4           set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00    1.372917                 38716        50 total

time 和 strace 结果不是同一个测试,所以数据略有不同。但我认为它可以显示一些东西。

我检查内核配置 CONFIG_HIGH_RES_TIMERS、CONFIG_HPET 和 CONFIG_HZ:

在 5.3 上:

$ cat /boot/config-`uname -r` |grep CONFIG_HIGH_RES_TIMERS
$ cat /boot/config-`uname -r` |grep CONFIG_HPET
CONFIG_HPET_TIMER=y
CONFIG_HPET_EMULATE_RTC=y
CONFIG_HPET=y
# CONFIG_HPET_RTC_IRQ is not set
# CONFIG_HPET_MMAP is not set
$ cat /boot/config-`uname -r` |grep CONFIG_HZ
# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
CONFIG_HZ_1000=y
CONFIG_HZ=1000

在 6.3 上:

$ cat /boot/config-`uname -r` |grep CONFIG_HIGH_RES_TIMERS
CONFIG_HIGH_RES_TIMERS=y
$ cat /boot/config-`uname -r` |grep CONFIG_HPET
CONFIG_HPET_TIMER=y
CONFIG_HPET_EMULATE_RTC=y
CONFIG_HPET=y
CONFIG_HPET_MMAP=y
$ cat /boot/config-`uname -r` |grep CONFIG_HZ
# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
CONFIG_HZ_1000=y
CONFIG_HZ=1000

其实我也在ARM和xubuntu13.04-amd64-desktop上尝试了arch上的代码,和cent os 6.3一样。

那么我该怎么做才能找出不同 CPU 使用率的原因呢?

它与内核配置有什么关系吗?

4

1 回答 1

5

你是对的,它与内核配置有关。usleep(1)将尝试休眠一微秒。在高分辨率计时器之前,不可能睡不到一瞬间(在你的情况下 HZ=1000 所以 1 jiffy == 1 毫秒)。

在没有这些高分辨率计时器的 CentOS 5.3 上,您会在 1ms 和 2ms[1] 之间休眠。在具有这些计时器的 CentOS 6.3 上,您的睡眠时间接近一微秒。这就是你在这个平台上使用更多 CPU 的原因:你只是轮询你的任务列表 500-1000 倍。

如果您将代码更改为usleep(1000),CentOS 5.3 的行为将相同。CentOS 6.3 cpu 时间将减少,并且与在 CentOS 5.3 上运行的程序处于同一水平

Linux 手册中对此进行了完整的讨论: run man 7 time

请注意,您的代码应该使用条件变量,而不是在某个时间间隔轮询您的任务列表。这是一种更有效、更干净的方式来做你正在做的事情。

此外,您的 main 应该真正加入线程,而不是仅仅睡 14 秒。

[1] 有一个例外。如果您的应用程序在实时调度策略(SCHED_FIFO 或 SCHED_RR)下运行,它会忙于等待而不是休眠以接近正确的数量。但默认情况下你需要root权限

于 2013-05-30T13:10:29.447 回答