Setting Thread Priority in Linux with Boost

Setting thread priority in Linux with Boost

That's the basic template for how I would do it but after searching around I found next to no code examples so I guess the verdict is out on whether it is best or not.

The problem is that boost::thread does not have a constructor that allows pthead attributes to be passed in at thread creation so you have to make changes after the thread starts. The only other way I know to get around that is through the process/thread schedule inheritance. Unless directed otherwise, new threads will inherit the schedule/priority of their creator so you could change the current thread before creating worker threads and then change back if you want. Seems awkward but it is an alternative.

Here's a hack of an example that hopefully demostrates both. You may need to change policy and priority as appropriate and run as root.

Be careful with the way you set the priority. Various restrictions apply.

#include <iostream>
#include <boost/thread/thread.hpp>
#include <unistd.h>
#include <sched.h>
#include <cstdio>

void* threadfunc()
{
sleep(5);
}

void displayAndChange(boost::thread& daThread)
{
int retcode;
int policy;

pthread_t threadID = (pthread_t) daThread.native_handle();

struct sched_param param;

if ((retcode = pthread_getschedparam(threadID, &policy, ¶m)) != 0)
{
errno = retcode;
perror("pthread_getschedparam");
exit(EXIT_FAILURE);
}

std::cout << "INHERITED: ";
std::cout << "policy=" << ((policy == SCHED_FIFO) ? "SCHED_FIFO" :
(policy == SCHED_RR) ? "SCHED_RR" :
(policy == SCHED_OTHER) ? "SCHED_OTHER" :
"???")
<< ", priority=" << param.sched_priority << std::endl;

policy = SCHED_FIFO;
param.sched_priority = 4;

if ((retcode = pthread_setschedparam(threadID, policy, ¶m)) != 0)
{
errno = retcode;
perror("pthread_setschedparam");
exit(EXIT_FAILURE);
}

std::cout << " CHANGED: ";
std::cout << "policy=" << ((policy == SCHED_FIFO) ? "SCHED_FIFO" :
(policy == SCHED_RR) ? "SCHED_RR" :
(policy == SCHED_OTHER) ? "SCHED_OTHER" :
"???")
<< ", priority=" << param.sched_priority << std::endl;
}

int main(int argc, char* argv[])
{
int policy, res;

struct sched_param param;

if ((policy = sched_getscheduler(getpid())) == -1)
{
perror("sched_getscheduler");
exit(EXIT_FAILURE);
}

if ((res = sched_getparam(getpid(), ¶m)) == -1)
{
perror("sched_getparam");
exit(EXIT_FAILURE);
}

std::cout << " ORIGINAL: ";
std::cout << "policy=" << ((policy == SCHED_FIFO) ? "SCHED_FIFO" :
(policy == SCHED_RR) ? "SCHED_RR" :
(policy == SCHED_OTHER) ? "SCHED_OTHER" :
"???")
<< ", priority=" << param.sched_priority << std::endl;

policy = SCHED_RR;
param.sched_priority = 2;

if ((res = sched_setscheduler(getpid(), policy, ¶m)) == -1)
{
perror("sched_setscheduler");
exit(EXIT_FAILURE);
}

boost::thread t1(&threadfunc);

displayAndChange(t1);

t1.join();

return 0;
}

C++ & boost::threads - How to prioritize thread based on work type?

As far as I know boost doesn't provide an API to do it (the C++11 standard certainly doesn't at least).

On Linux, you can nice or setpriority each thread independently from the others. Note however that this is not POSIX-conformant:

According to POSIX, the nice value is a per-process setting. However, under the current Linux/NPTL implementation of POSIX threads, the nice value is a per-thread attribute: different threads in the same process can have different nice values. Portable applications should avoid relying on the Linux behavior, which may be made standards conformant in the future.

Since Linux uses pthreads (and so does the Linux port of boost) you could also use pthread_setschedparam which has the advantage of being more portable than the Linux-specific per-thread nice behaviour.

In both cases, there's the slight uneasiness due to having to resort to system facilities in order to manage supposedly "opaque" boost (or std in C++11) resources, so tread carefully (as with anything implementation-specific).

Performance/priority in Boost thread with accept() (Linux)

if you or the class you use is doing an accept call, then the thread is blocked and is waiting for the OS to do some things. SO the thread is (should) not be consuming any CPU ressources, if it does so, it is either

  • within the system call (nothing you could change) or
  • there is a time-out and the thread is looping to accept again. If
    there is any parameter to change this, try it!

Boost: how to set program priority?

There's no generalised cross-platform priority support in boost itself.

#ifdef is your friend...

See Tom's answer for the win32 solution.

On Linux you'd use the nice call (or possibly setpriority). Don't be put off by those document's statements that they adjust process priority; on Linux a thread is just a process which shares a memory space with some other process/processes. If you get yourself a better version of "top" which lists the individual threads, you can see the nice levels of each.

Note that a process/thread with normal user privileges can only reduce its priority (higher "nice" value) on Linux. The little bit of work with priorities I've done on Windows, it seemed anything goes (but that was on XP; situation may be different post-Vista, UAC etc).

Set a higher priority to a boost::asio thread wrt the process

I'm with the commenters that doubt this will be useful.

But to answer your question: there is no such thing as a Boost Asio thread.

It is explicitly documented why:

Threads And Boost Asio

Consequently, it is the library user's responsibility to create and
manage all threads to which the notifications will be delivered.

The reasons for this approach include:

  • By only calling io_context::run() from a single thread, the user's code can avoid the development complexity associated with
    synchronisation. For example, a library user can implement scalable
    servers that are single-threaded (from the user's point of view).
  • A library user may need to perform initialisation in a thread shortly after the thread starts and before any other application code
    is executed. For example, users of Microsoft's COM must call
    CoInitializeEx before any other COM operations can be called from that
    thread.
  • The library interface is decoupled from interfaces for thread creation and management, and permits implementations on platforms
    where threads are not available.

So, you create your own threads - except the main thread I suppose - and can do so in whatever fashion you require.

Equivalent of SetThreadPriority on Linux (pthreads)

The equivalent to SetThreadPriority in linux would be pthread_setschedprio(pthread_t thread, int priority).

Check the man page.

EDIT: here's the sample code equivalent:

#include <pthread.h>

int main()
{
pthread_t thId = pthread_self();
pthread_attr_t thAttr;
int policy = 0;
int max_prio_for_policy = 0;

pthread_attr_init(&thAttr);
pthread_attr_getschedpolicy(&thAttr, &policy);
max_prio_for_policy = sched_get_priority_max(policy);

pthread_setschedprio(thId, max_prio_for_policy);
pthread_attr_destroy(&thAttr);

return 0;
}

This sample is for the default scheduling policy which is SCHED_OTHER.

EDIT: thread attribute must be initialized before usage.



Related Topics



Leave a reply



Submit