nice()函数是用来改变线程优先级还是进程优先级?

23
nice命令的man页面上写道:“nice()将inc添加到调用进程的nice值中。那么,我们可以使用它来改变由pthread_create创建的线程的nice值吗?” 编辑: 似乎我们可以为每个线程设置不同的nice值。 我编写了一个应用程序,为不同的线程设置了不同的nice值,并观察到“更好”的线程以较低的优先级被调度。检查输出,我发现字符串“high priority ........”输出得更频繁。
void * thread_function1(void *arg)
{
  const pid_t tid = syscall(SYS_gettid);

  int ret = setpriority(PRIO_PROCESS, tid, -10);
  printf("tid of high priority thread %d , %d\n", tid ,getpriority(PRIO_PROCESS, tid));
  while(1)
  {
    printf("high priority ................\n");
  }
}


void * thread_function(void *arg)
{
  const pid_t tid = syscall(SYS_gettid);
  int ret = setpriority(PRIO_PROCESS, tid, 10);
  printf("tid of low priority thread %d , %d \n", tid ,getpriority(PRIO_PROCESS, tid));
  while(1)
  {
    printf("lower priority\n");
  }
}


int main()
{
  pthread_t id1;
  pthread_t id2;

  pid_t pid = getpid();
  pid_t tid = syscall(SYS_gettid);

  printf("main thread : pid = %d , tid = %d \n" , pid, tid);
  pthread_create(&id1, NULL, thread_function1,  NULL);
  pthread_create(&id2, NULL,thread_function,   NULL);

  pthread_join(id1, NULL);
  pthread_join(id2, NULL);
}

以下是此代码所包含的库文件: #include<cstdio> #include<pthread.h> #include<unistd.h> #include<sys/syscall.h> #include<sys/resource.h> - joepol
3个回答

36

pthreads手册上说:

POSIX.1 还要求线程共享一系列其他属性(即这些属性是进程范围而不是每个线程的):

[...]

  • 好值(setpriority(2))

因此,理论上,“好值”是进程全局的,并且由所有线程共享,您不应该能够为一个或多个单独的线程设置特定的好值。

然而,同样的手册还说:

LinuxThreads

这个实现的显着特点如下:

[...]

  • 线程不共享通用好值。

NPTL

[...]

NPTL 仍然有一些与 POSIX.1 不一致之处:

  • 线程不共享通用好值。

因此,事实证明,Linux 上的两种线程实现(LinuxThreads 和 NPTL)实际上违反了 POSIX.1,您可以通过在这些系统上向 setpriority() 传递 tid 来为一个或多个单独的线程设置特定的好值。


1
但为什么在某些JVM实现中,Java线程的优先级与nice值具有1:1的映射关系呢?//www.javamex.com/tutorials/threads/priority_what.shtml此外,我编写了一个应用程序,为不同的线程设置不同的nicer 值,并观察了输出频率以检查该nicer线程是否被安排到更低的优先级。 - pierrotlefou
@pierr,有趣的是,原来NPTL和Linux线程都违反了POSIX.1标准。我会更新我的回答。 - Frédéric Hamidi
@FrédéricHamidi,Linux上的线程仍然不共享相同的nice值吗? - Chenna V
1
@blueskin,Frédéric 给出了答案:看一下 man 手册。很可能不遵循 POSIX,因为就操作系统而言,每个线程都是一个独立的任务。 - Alexis Wilke

0

我想测试更改这些值如何影响线程优先级,因此我将您的片段修改为以下基准测试:

  • 在默认的SCHED_OTHER调度策略下运行
  • 创建了12个低优先级线程,以确保它们在Red hat 7上的8个核心上“竞争资源”(cat /proc/cpuinfo
  • 修改了thread_function()以执行一些“数字计算工作”

当设置为边缘优先级时,您可以明显看到高优先级线程更频繁地运行,但其他线程不会出现饥饿情况。相关字段是NITIME+

Thread's NICE level and timing view

来自顶部手册页面

NI -- 美好值 任务的美好值。负的美好值意味着更高的优先级,而正的美好值意味着更低的优先级。在此字段中的零仅意味着在确定任务的分派能力时不会调整优先级。

TIME -- CPU时间 任务自启动以来使用的总CPU时间。

#include<cstdio> 
#include<pthread.h> 
#include<unistd.h> 
#include<sys/syscall.h> 
#include<sys/resource.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 12
 
struct ThreadParams{
 const char* priority;
 const int niceLevel;
};

void * thread_function(void *arg)
{
  const pid_t tid = syscall(SYS_gettid);


  struct ThreadParams* params = (ThreadParams*)arg; 

  int ret = setpriority(PRIO_PROCESS, tid, params->niceLevel);
  printf("tid of %s priority thread %d , %d\n", params->priority, tid ,getpriority(PRIO_PROCESS, tid));
  long long int count = 0;
  while(1)
  {
      count++;
      if(count == 10000000000) //10^10 iterations
      {
          printf("%s priority ................\n", params->priority);
          count = 0;
      }
  }
}



int main()
{
  pthread_t tIdHigh;
  pthread_t tIdsLow[NUM_THREADS];

  pid_t pid = getpid();
  pid_t tid = syscall(SYS_gettid);

  printf("main thread : pid = %d , tid = %d \n" , pid, tid);
  
  struct ThreadParams highParams = {"High", -20};
  struct ThreadParams lowParams  = {"Low", 19};

  for(int i=0; i < NUM_THREADS ; i++)
  {
    pthread_create(&(tIdsLow[i]), NULL,thread_function,  &lowParams);
  }
  
  pthread_create(&tIdHigh, NULL, thread_function,  &highParams);
  
  for(int i=0; i < NUM_THREADS ; i++)
  {
    pthread_join(tIdsLow[i], NULL);
  }
  pthread_join(tIdHigh, NULL);
  return 0;

}

使用 g++ <FILE_NAME>.cpp -lpthread 编译。

运行 top -H -p $(pidof <PROCESS_NAME>) 来启用线程模式并获取特定进程的信息。


0
根据setpriority的man页面,较低的nice值(nice值在-2020的范围内)意味着更高的调度优先级。看起来你的程序按预期工作了(nice = -10使该线程具有更高的优先级)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接