【发布时间】: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 语句以确保它们正常运行。
标签: linux multithreading linux-kernel pthreads