pthread高优先级线程的优先效果试验

[tag: pthread 优先级 效果 试验 多核CPU]

WARNING: 试验程序之前注意保存正在编辑的东西,以防某些数值设置大了导致PC一直假死。

先给出示例程序如下:
--------------------------------------------------------------------------------
#include
#include
#include
#include
#include

#define PRINTF(fmt, ...)    printf("%s,%d:\t" fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__)

#define THREAD_NUM      11 // 9 // 7 // 
#define PRIOR_THREAD    -1//(THREAD_NUM - 1) // -1
#define SLEEP           1
#define SLEEP_FREQ      10
#define LOOP_NUM        100000000
#define POLICY          SCHED_RR // SCHED_FIFO // 

void* thread(void* p) {
    int i;

    for (i = 0; i < LOOP_NUM; i++) {
        if (0 == i % (LOOP_NUM / SLEEP_FREQ)) {
            usleep(SLEEP);
        }
    }

    PRINTF("thread%d done\n", NULL != p ? *(int*)p : -11111111);

    return NULL;
}

int main() {
    pthread_t             threads[THREAD_NUM], id;
    pthread_attr_t        attrs[THREAD_NUM];
    struct sched_param    scheds[THREAD_NUM], sched;
    int                   idxs[THREAD_NUM];
    int                   policy, i, ret;

    id = pthread_self();
    ret = pthread_getschedparam(id, &policy, &sched);
    if (ret != 0) {
        PRINTF("get main sched ERROR, ret=%d\n", ret);
    }
    sched.sched_priority = sched_get_priority_max(POLICY);
    ret = pthread_setschedparam(id, POLICY, &sched);
    if (ret != 0) {
        PRINTF("set main sched ERROR, ret=%d\n", ret);
    }

    for (i = 0; i < THREAD_NUM; i++) {
        idxs[i] = i;
        ret = pthread_attr_init(&attrs[i]);
        if (ret != 0) {
            PRINTF("init attr %d ERROR, ret=%d\n", idxs[i], ret);
        }
        ret = pthread_attr_getschedparam(&attrs[i], &scheds[i]);
        if (ret != 0) {
            PRINTF("get attr sched %d ERROR, ret=%d\n", idxs[i], ret);
        }
        ret = pthread_attr_setschedpolicy(&attrs[i], POLICY);
        if (ret != 0) {
            PRINTF("set arrt schedpolicy %d ERROR, ret=%d\n", idxs[i], ret);
        }
        if (PRIOR_THREAD == i) {
            scheds[i].sched_priority = sched_get_priority_max(POLICY);
        }
        else {
            scheds[i].sched_priority = sched_get_priority_min(POLICY);
        }
        ret = pthread_attr_setschedparam(&attrs[i], &scheds[i]);
        if (ret != 0) {
            PRINTF("set attr sched %d ERROR, ret=%d\n", idxs[i], ret);
        }
        ret = pthread_attr_setinheritsched(&attrs[i], PTHREAD_EXPLICIT_SCHED);
        if (ret != 0) {
            PRINTF("set arrt inheritsched %d ERROR, ret=%d\n", idxs[i], ret);
        }
        PRINTF("thread%d priority=%d\n", idxs[i], scheds[i].sched_priority);
    }

    for (i = 0; i < THREAD_NUM; i++) {
        ret = pthread_create(&threads[i], &attrs[i], thread, &idxs[i]);
        if (ret != 0) {
            PRINTF("create thread%d ERROR, ret=%d\n", idxs[i], ret);
        }
    }
    for (i = 0; i < THREAD_NUM; i++) {
        ret = pthread_join(threads[i], NULL);
        if (ret != 0) {
            PRINTF("join thread%d ERROR, ret=%d\n", idxs[i], ret);
        }
    }

    return 0;
}
--------------------------------------------------------------------------------

要想试验出高优先级的线程的优先效果,就应该让CPU有足够的负荷,否则CPU有空闲,就没有线程会被抢占,高优先级的线程的优先就不会被体现出来。
所以,thread函数的编写,以及LOOP_NUM、SLEEP等宏值的设定,都应该使CPU很忙。
关于LOOP_NUM这个宏的值,试验时,可以先设置小些,然后逐渐调大,保证线程运行的时间足够长,别刚启动就执行完了而没有被抢占的机会;
同时也别太大,否则程序运行一次的时间太长。

在main函数中,首先设置了main函数所在的线程的优先级为max,这很重要,因为要保证所有线程尽量在同一起跑线上,否则影响试验效果。
剩下的就是设置调度策略、设置优先级、启动线程之类的事了。

下面开始试验,将PRIOR_THREAD设为THREAD_NUM-1,即将优先级最高的线程的编号设为THREAD_NUM-1,
此时,比如THREAD_NUM设置为7时,优先级最高的线程则是thread6。

下面列出在有8个线程的CPU上,THREAD_NUM分别设为7、9、11的试验结果:
THREAD_NUM设置为7,thread6不会最先done,而将同样的可执行文件放入设有2个CPU核的虚拟机中,thread6会最先done;
THREAD_NUM设置为9,即仅仅比CPU的核/线程数大1,thread8大多数时候会最先done,而有时不是;
THREAD_NUM设置为11,thread10总是最先done。

试验结果猜想:
一个线程不能同时独占所有的CPU核/线程,当THREAD_NUM小于CPU的核/线程时,包括最高优先级线程在内的所有线程都有CPU核/线程可用,所以所有线程都不会被抢占,也就相当于没有了优先级区别;
并且,最高优先级线程不是最先被创建的,执行的晚,done的时候也就晚。
在多核/多线程CPU上要注意,THREAD_NUM要大于CPU的核/线程数,且最好不仅仅比CPU的核/线程数大1。

有了猜想,以后就可以带着这个猜想,进一步研究pthread。

你可能感兴趣的:(Programming)