使用 pthread 调度策略和优先级没有任何区别
Posted
技术标签:
【中文标题】使用 pthread 调度策略和优先级没有任何区别【英文标题】:Scheduling policy and priority using pthread does not make any difference 【发布时间】:2021-12-25 06:54:38 【问题描述】:我正在使用 pthread 运行一个简单的多线程程序。考虑使用实时调度程序(SCHED_FIFO 策略),低优先级线程将无法运行,直到高优先级线程完成。但是,当我同时运行这个程序的两个版本(唯一的区别是优先级 99->1)时,它们几乎同时完成。我什至将策略更改为 SCHED_OTHER,但仍然没有区别。
# include <stdio.h>
# include <string.h>
# include <pthread.h>
# include <stdlib.h>
# include <unistd.h>
# include <math.h>
# define NUM_THREADS 128
pthread_t tid[NUM_THREADS];
int indexes[NUM_THREADS];
void* dummyThread(void *arg)
unsigned long i = 0;
pthread_t id = pthread_self();
float a, b = 5, c = 8;
printf("Thread %d started.\n", *(int*)arg + 1);
for(i = 0; i < 10000000; i++)
a = sin(b) + sqrt(b);
printf("Thread %d finished.\n", *(int*)arg + 1);
return NULL;
int main(void)
int i = 0;
pthread_attr_t attr;
struct sched_param schedParam;
struct timespec start, finish;
double elapsed;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
schedParam.sched_priority = 1;
pthread_attr_setschedparam(&attr, &schedParam);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
clock_gettime(CLOCK_MONOTONIC, &start);
for (i = 0 ; i < NUM_THREADS; i++)
indexes[i] = i;
if (!pthread_create((void*)&tid[i], &attr, &dummyThread, &indexes[i]))
printf("Thread %d created successfully.\n", i + 1);
else
printf("Failed to create Thread %d.\n", i + 1);
for (i = 0 ; i < NUM_THREADS; i++)
pthread_join(tid[i], NULL);
clock_gettime(CLOCK_MONOTONIC, &finish);
elapsed = (finish.tv_sec - start.tv_sec);
elapsed += (finish.tv_nsec - start.tv_nsec) / 1000000000.0;
printf("%lf\n", elapsed);
return 0;
编辑 1:通过添加 pthread_attr_setschedparam
和错误检查更新了我的代码。在没有 sudo 的情况下运行它时我没有收到任何错误,并且更改优先级或调度策略仍然不会改变结果。
编辑 2:我注意到当我在同一进程中创建具有不同优先级的线程时,它运行良好。在下面的代码中,对于偶数索引的线程,我分配优先级 1,而对于奇数索引的线程,我分配优先级 99。它运行良好,奇数线程在偶数线程之前先完成。
# include <stdio.h>
# include <string.h>
# include <pthread.h>
# include <stdlib.h>
# include <unistd.h>
# include <math.h>
# define NUM_THREADS 128
pthread_t tid[NUM_THREADS];
int indexes[NUM_THREADS];
void* dummyThread(void *arg)
unsigned long i = 0;
pthread_t id = pthread_self();
float a, b = 5, c = 8;
printf("Thread %d started.\n", *(int*)arg);
for(i = 0; i < 10000000; i++)
a = sin(b) + sqrt(b);
printf("Thread %d finished.\n", *(int*)arg);
return NULL;
int main(void)
int i = 0;
pthread_attr_t attr;
struct sched_param schedParam;
struct timespec start, finish;
double elapsed;
clock_gettime(CLOCK_MONOTONIC, &start);
for (i = 0 ; i < NUM_THREADS; i++)
indexes[i] = i;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
schedParam.sched_priority = i % 2 == 0 ? 1 : 99;
pthread_attr_setschedparam(&attr, &schedParam);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
if (!pthread_create((void*)&tid[i], &attr, &dummyThread, &indexes[i]))
printf("Thread %d created successfully.\n", i);
else
printf("Failed to create Thread %d.\n", i);
for (i = 0 ; i < NUM_THREADS; i++)
pthread_join(tid[i], NULL);
clock_gettime(CLOCK_MONOTONIC, &finish);
elapsed = (finish.tv_sec - start.tv_sec);
elapsed += (finish.tv_nsec - start.tv_nsec) / 1000000000.0;
printf("%lf\n", elapsed);
return 0;
由于来自不同进程的线程都被发送到内核中的同一个调度程序,我不知道为什么它不适用于不同的进程。
【问题讨论】:
为什么会有任何不同? N 个核心有 X 量的工作要做。改变优先级并不会改变这一点。 您需要做的第一件事是检查所有pthread_..
函数是否有错误返回。除非您以 root
的身份运行二进制文件,否则您的 pthread_attr_setschedparam
可能会失败。
@MartinJames 是的,工作量是一样的。但是当所有 CPU 内核都被占用时,调度程序会优先考虑具有更高优先级的线程。如果它们在并行运行时共享相同数量的 CPU 时间,优先级是什么?
@EmployedRussian 是的,我已经检查过了。没有错误,它们运行正常。我已经简化了上面的代码,但是我在创建线程时会检查错误,并且在线程中还有 printf 语句以确保它们正常运行。
【参考方案1】:
来自男人pthread_attr_setschedpolicy
为了使政策设置由 pthread_attr_setschedpolicy() 在调用时生效 pthread_create(3),调用者必须使用 pthread_attr_setinheritsched(3) 设置继承调度程序 属性对象 attr 的属性 PTHREAD_EXPLICIT_SCHED。
你忽略了这样做,所以你的SCHED_FIFO
没有任何效果。
一旦我添加了pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
调用,pthread_create()
就会以EPERM
开始失败(因为只有root
可以创建SCHED_FIFO
线程)。
【讨论】:
这很有趣,因为即使我添加pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED)
,我也没有收到任何错误。并且无论是否使用sudo
运行代码,它仍然忽略了优先级和调度程序。
你知道为什么会这样吗?
@AmirFakhimBabaei 我没有。也许你在错误的地方添加了pthread_attr_setinheritsched()
?我在pthread_attr_setschedparam()
通话后立即添加了它。你检查它是否成功?编辑您的问题并显示确切来源,包括错误检查?
我刚刚更新了我的代码。
@AmirFakhimBabaei 运行你的确切代码给我Failed to create Thread 1. Failed to create Thread 2. ...
。您使用的是什么 Linux 和 libc
?您是在WSL2
或某种模拟器下运行它吗?如果没有sudo
,我看不出这段代码如何工作。以上是关于使用 pthread 调度策略和优先级没有任何区别的主要内容,如果未能解决你的问题,请参考以下文章
Linux 内核线程调度示例一 ④ ( pthread_attr_init 初始化线程属性对象 | 完整代码示例 )
Linux 内核线程调度示例一 ④ ( pthread_attr_init 初始化线程属性对象 | 完整代码示例 )
Linux 内核进程优先级与调度策略 ③ ( 设置获取线程优先级的核心函数 | 修改线程调度策略函数 )