はじめに
pthreadの関数を使用して、スレッドプライオリティを設定する方法を解説していきます。
プライオリティの設定方法は、2種類あります。
- pthread_attr_tを利用してスレッド生成前に設定する
- スレッド生成後に設定する
どちらも共通して、root権限で実行しないとエラーとなります。
1. スレッド生成前に設定する方法
流れとしては、以下のとおりです。
- pthread_attr_init()でpthread_attr_tを初期化
- pthread_attr_setinheritsched()でattrからスケジューリング属性を取得するように指定する
- pthread_attr_setschedpolicy()でスケジューリングポリシーを設定する
- pthread_attr_setschedparam()でプライオリティを設定する
以下はサンプルコードです。
# include <iostream>
# include <pthread.h>
# include <sched.h>
# define NUM_OF_THREADS 4
pthread_mutex_t mtx;
void* entry(void* arg)
{
    struct sched_param param;
    int policy{};
    int ret = pthread_getschedparam(pthread_self(), &policy, ¶m);
    if (ret != 0)
    {
        std::cout << "pthread_getschedparam() error[" << ret << "]\n";
    }
    
    pthread_mutex_lock(&mtx);
    std::cout << "Priority:" << param.sched_priority << " start\n";
        
    pthread_mutex_unlock(&mtx);
    // do some work
    return NULL;
}
int main()
{
    pthread_mutex_init(&mtx, NULL);
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    int ret = pthread_attr_setinheritsched(¶m, PTHREAD_EXPLICIT_SCHED);
    if (ret != 0)
    {
        std::cout << "pthread_attr_setinheritsched() error[" << ret << "]¥n";
    }
    ret = pthread_attr_setschedpolicy(&attr, SCHED_RR);
    if (ret != 0)
    {
        std::cout << "pthread_attr_setschedpolicy() error[" << ret << "]¥n";
    }
    pthread_t threads[NUM_OF_THREADS];
    for (int i = 0; i < NUM_OF_THREADS; i++)
    {
        param.sched_priority = i + 1;
        ret = pthread_attr_setschedparam(&attr, ¶m);
        if (ret != 0)
        {
            std::cout << "pthread_attr_setschedparam() error[" << ret << "]¥n";
        }
        
        ret = pthread_create(&threads[i], &attr, entry, NULL);
        if (ret != 0)
        {
            std::cout << "pthread_create() error[" << ret << "]¥n";
        }
    }
    for (int i = 0; i < NUM_OF_THREADS; i++)
    {
        pthread_join(threads[i], NULL);
    }
    pthread_attr_destroy(&attr);
    pthread_mutex_destroy(&mtx);
    return 0;
}
2. スレッド生成後に設定する方法
pthread_create()でスレッドを生成したあとで、pthread_setschedparam()関数を使用してスレッドを設定します。
# include <iostream>
# include <pthread.h>
# include <sched.h>
# define NUM_OF_THREADS 4
pthread_mutex_t mtx;
void* entry(void* arg)
{
    pthread_mutex_lock(&mtx);
    struct sched_param param;
    int policy{};
    int ret = pthread_getschedparam(pthread_self(), &policy, ¶m);
    if (ret != 0)
    {
        std::cout << "pthread_getschedparam() error[" << ret << "]\n";
    }
    pthread_mutex_unlock(&mtx);
    
    pthread_mutex_lock(&mtx);
    std::cout << "Priority:" << param.sched_priority << " start\n";
        
    pthread_mutex_unlock(&mtx);
    // do some work
    return NULL;
}
int main()
{
    pthread_mutex_init(&mtx, NULL);
    pthread_t threads[NUM_OF_THREADS];
    struct sched_param param;
    pthread_mutex_lock(&mtx);
    for (int i = 0; i < NUM_OF_THREADS; i++)
    {
        ret = pthread_create(&threads[i], &attr, entry, NULL);
        if (ret != 0)
        {
            std::cout << "pthread_create() error[" << ret << "]¥n";
        }
    }
    for (int i = 0; i < NUM_OF_THREADS; i++)
    {
        param.sched_priority = i + 1;
        ret = pthread_setschedparam(threads[i], SCHED_RR, ¶m);
        if (ret != 0)
        {
            std::cout << "pthread_setschedparam() error[" << ret << "]¥n";
        }
    }
    for (int i = 0; i < NUM_OF_THREADS; i++)
    {
        pthread_join(threads[i], NULL);
    }
    pthread_mutex_destroy(&mtx);
    return 0;
}
本来は、同一CPU上で異なるプライオリティのスレッドを動かしたら、それぞれのスレッドのスループットに差が発生するかという検証をする予定でした。
しかし、CPUアフィニティを設定して同一CPU上で複数スレッドを実行するコードを実行すると、アプリケーションが固まってしまうという問題に遭遇。
このあたりの情報をご存じの方がいらっしゃたら、ぜひ教えていただけると嬉しいです。