pierrotlefou
pierrotlefou

Reputation: 40721

is nice() used to change the thread priority or the process priority?

The man page for nice says "nice() adds inc to the nice value for the calling process. So, can we use it to change the nice value for a thread created by pthread_create?

EDIT: It seems that we can set the nice value per thread.

I wrote an application, setting different nice values for different threads, and observed that the "nicer" thread has been scheduled with lower priority. Checking the output, I found that the string "high priority ................" gets outputted more frequently.

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

Upvotes: 23

Views: 22021

Answers (3)

joepol
joepol

Reputation: 842

I wanted to test how changing these values really affects the thread's priority, so I modified your snippet to this benchmark:

  • Running on default SCHED_OTHER scheduling policy
  • Created 12 low priority threads to make sure they compete on resources - on Red hat 7 with 8 cores. (cat /proc/cpuinfo)
  • Modified the thread_function() to do some "number crunching work"

When setting to edge priorities you can definitely see with top -H that the high priority thread runs more often, but no starvation occurs to other threads. relevant fields are NI and TIME+

Thread's NICE level and timing view

From top man page:

NI -- Nice Value The nice value of the task. A negative nice value means higher priority, whereas a positive nice value means lower priority. Zero in this field simply means priority will not be adjusted in determining a task's dispatch-ability.

TIME -- CPU Time Total CPU time the task has used since it started.

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

}

Compiled with g++ <FILE_NAME>.cpp -lpthread.

Run top -H -p $(pidof <PROCESS_NAME>) to enable Threads-mode and get information for specific process

Upvotes: 0

Andrzej
Andrzej

Reputation: 7

According to the man page for setpriority, a lower nice value (nice values are in the range of -20 to 20) means higher priority in scheduling. It looks like your program works as expected (nice = -10 gives this thread higher priority).

Upvotes: -1

Fr&#233;d&#233;ric Hamidi
Fr&#233;d&#233;ric Hamidi

Reputation: 262939

The pthreads man page says:

POSIX.1 also requires that threads share a range of other attributes (i.e., these attributes are process-wide rather than per-thread):

[...]

  • nice value (setpriority(2))

So, theoretically, the "niceness" value is global to the process and shared by all threads, and you should not be able to set a specific niceness for one or more individual threads.

However, the very same man page also says:

LinuxThreads

The notable features of this implementation are the following:

[...]

  • Threads do not share a common nice value.

NPTL

[...]

NPTL still has a few non-conformances with POSIX.1:

  • Threads do not share a common nice value.

So it turns out that both threading implementations on Linux (LinuxThreads and NPTL) actually violate POSIX.1, and you can set a specific niceness for one or more individual threads by passing a tid to setpriority() on these systems.

Upvotes: 36

Related Questions