multithreading - 每个核心有多少个线程?

标签 multithreading core

我正在我的计算机上运行一个多线程程序,该计算机具有4 核。我正在创建以 SCHED_FIFO、SCHED_OTHER 和 SCHED_RR 优先级运行的线程。每种类型可以同时运行的线程的最大数量是多少?

例如, 我很确定一次只能运行四个 SCHED_FIFO 线程(每个核心一个) 但我不确定另外两个。

编辑我的代码,按照要求(它很长,但大部分是为了测试每个线程完成延迟任务的时间)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>

void *ThreadRunner(void *vargp);
void DisplayThreadSchdStats(void);
void delayTask(void);

int threadNumber = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

#define NUM_THREADS    9

//used to store the information of each thread
typedef struct{
    pthread_t  threadID;
    int policy;
    struct sched_param param;
    long startTime;
    long taskStartTime;
    long endTime1;
    long endTime2;
    long endTime3;
    long runTime;
    char startDate[30];
    char endDate[30];
}ThreadInfo;

ThreadInfo myThreadInfo[NUM_THREADS];



//main function
int main(void){

   printf("running...\n");

   int fifoPri = 60;
   int rrPri = 30;

   //create the 9 threads and assign their scheduling policies
   for(int i=0; i<NUM_THREADS; i++){

       if(i%3 == SCHED_OTHER){
            myThreadInfo[i].policy = SCHED_OTHER;
            myThreadInfo[i].param.sched_priority = 0;
       }
       else if (i%3 == SCHED_FIFO){ 
            myThreadInfo[i].policy = SCHED_RR;
            myThreadInfo[i].param.sched_priority = rrPri++; 
       }
       else{
            myThreadInfo[i].policy = SCHED_FIFO; 
            myThreadInfo[i].param.sched_priority = fifoPri++; 
       }
       pthread_create( &myThreadInfo[i].threadID, NULL, ThreadRunner, &myThreadInfo[i]);
pthread_cond_wait(&cond, &mutex);
   }

   printf("\n\n");


   //join each thread
   for(int g = 0; g < NUM_THREADS; g++){
      pthread_join(myThreadInfo[g].threadID, NULL);
   }


   //print out the stats for each thread
   DisplayThreadSchdStats();


   return 0;
}


//used to print out all of the threads, along with their stats
void DisplayThreadSchdStats(void){

   int otherNum = 0;
   long task1RR = 0;
   long task2RR = 0;
   long task3RR = 0;
   long task1FIFO = 0;
   long task2FIFO = 0;
   long task3FIFO = 0;
   long task1OTHER = 0;
   long task2OTHER = 0;
   long task3OTHER = 0;

   for(int g = 0; g < threadNumber; g++){

      printf("\nThread# [%d]  id [0x%x] exiting...\n", g + 1, (int) myThreadInfo[g].threadID);
      printf("DisplayThreadSchdStats:\n");
      printf("   threadID    = 0x%x \n", (int) myThreadInfo[g].threadID);

      if(myThreadInfo[g].policy == 0){
         printf("   policy      = SHED_OTHER\n");
         task1OTHER += (myThreadInfo[g].endTime1 - myThreadInfo[g].taskStartTime); 
         task2OTHER += (myThreadInfo[g].endTime2 - myThreadInfo[g].endTime1);
         task3OTHER += (myThreadInfo[g].endTime3 - myThreadInfo[g].endTime2);
         otherNum++;
      }
      if(myThreadInfo[g].policy == 1){
         printf("   policy      = SHED_FIFO\n");
         task1FIFO += (myThreadInfo[g].endTime1 - myThreadInfo[g].taskStartTime); 
         task2FIFO += (myThreadInfo[g].endTime2 - myThreadInfo[g].endTime1);
         task3FIFO += (myThreadInfo[g].endTime3 - myThreadInfo[g].endTime2);

      }
      if(myThreadInfo[g].policy == 2){
         printf("   policy      = SHED_RR\n");
         task1RR+= (myThreadInfo[g].endTime1 - myThreadInfo[g].taskStartTime); 
         task2RR += (myThreadInfo[g].endTime2 - myThreadInfo[g].endTime1);
         task3RR += (myThreadInfo[g].endTime3 - myThreadInfo[g].endTime2);

      }



      printf("   priority    = %d \n", myThreadInfo[g].param.sched_priority);
      printf("   startTime   = %s\n", myThreadInfo[g].startDate);
      printf("   endTime     = %s\n", myThreadInfo[g].endDate);
      printf("   Task start TimeStamp in micro seconds [%ld]\n", myThreadInfo[g].taskStartTime);
      printf("   Task end   TimeStamp in micro seconds [%ld] Delta [%lu]us\n", myThreadInfo[g].endTime1 , (myThreadInfo[g].endTime1 - myThreadInfo[g].taskStartTime));
      printf("   Task end   Timestamp in micro seconds [%ld] Delta [%lu]us\n", myThreadInfo[g].endTime2, (myThreadInfo[g].endTime2 - myThreadInfo[g].endTime1));
      printf("   Task end   Timestamp in micro seconds [%ld] Delta [%lu]us\n\n\n", myThreadInfo[g].endTime3, (myThreadInfo[g].endTime3 - myThreadInfo[g].endTime2));
      printf("\n\n");


   }

   printf("Analysis: \n");
   printf("  for SCHED_OTHER, task 1 took %lu,  task2 took %lu,  and task 3 took %lu.   (average = %lu)\n", (task1OTHER/otherNum), (task2OTHER/otherNum), (task3OTHER/otherNum), (task1OTHER/otherNum + task2OTHER/otherNum + task3OTHER/otherNum)/3 );
   printf("  for SCHED_RR,    task 1 took %lu,  task2 took %lu,  and task 3 took %lu.   (average = %lu)\n", (task1RR/otherNum), (task2RR/otherNum), (task3RR/otherNum), (task1RR/otherNum + task2RR/otherNum + task3RR/otherNum)/3 );
   printf("  for SCHED_FIFO,  task 1 took %lu,  task2 took %lu,  and task 3 took %lu.   (average = %lu)\n", (task1FIFO/otherNum), (task2FIFO/otherNum), (task3FIFO/otherNum) , (task1FIFO/otherNum + task2FIFO/otherNum + task3FIFO/otherNum)/3);

}





//the function that runs the threads
void *ThreadRunner(void *vargp){


   pthread_mutex_lock(&mutex);


   char date[30];
   struct tm *ts;
   size_t last;
   time_t timestamp = time(NULL);
   ts = localtime(&timestamp);
   last = strftime(date, 30, "%c", ts);
   threadNumber++;
   ThreadInfo* currentThread;
   currentThread = (ThreadInfo*)vargp;


   //set the start time
   struct timeval  tv;
   gettimeofday(&tv, NULL);
   long milltime0 = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000;
   currentThread->startTime = milltime0;

   //set the start date
   strcpy(currentThread->startDate, date);

   if(pthread_setschedparam(pthread_self(), currentThread->policy,(const struct sched_param *) &(currentThread->param))){
      perror("pthread_setschedparam failed");
      pthread_exit(NULL);
   }

   if(pthread_getschedparam(pthread_self(), &currentThread->policy,(struct sched_param *) &currentThread->param)){
      perror("pthread_getschedparam failed");
      pthread_exit(NULL);
   }

   gettimeofday(&tv, NULL);
   long startTime = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000;
   currentThread->taskStartTime = startTime;
   //delay task #1
   delayTask();

   //set the end time of task 1
   gettimeofday(&tv, NULL);
   long milltime1 = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000;
   currentThread->endTime1 = milltime1;


   //delay task #2
   delayTask();

   //set the end time of task 2
   gettimeofday(&tv, NULL);
   long milltime2 = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000;
   currentThread->endTime2 = milltime2;


   //delay task #3
   delayTask();

   //set the end time of task 3
   gettimeofday(&tv, NULL);
   long milltime3 = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000;
   currentThread->endTime3 = milltime3;


   //set the end date
   timestamp = time(NULL);
   ts = localtime(&timestamp);
   last = strftime(date, 30, "%c", ts);
   strcpy(currentThread->endDate, date);


   //set the total run time of the thread
   long runTime = milltime3 - milltime0;
   currentThread->runTime = runTime;

   //unlock mutex
   pthread_mutex_unlock(&mutex);
   pthread_cond_signal(&cond);

   pthread_exit(NULL);
}

//used to delay each thread
void delayTask(void){
   for(int i = 0; i < 5000000; i++){
      printf("%d", i % 2);
   }

}

最佳答案

简而言之:不能保证有多少线程将并行运行,但所有线程都将同时运行。

无论您在通用操作系统控制的应用程序中启动多少个线程,它们都将并发运行。也就是说,将为每个线程提供一些非零的运行时间,并且不保证操作系统定义的同步原语(等待互斥体、锁等)之外的线程部分的特定执行顺序。对线程数量的唯一限制可能是由操作系统施加的 policies .

在任何给定时间,有多少线程将被选择并行运行尚未定义。该数量显然不能超过操作系统可见的逻辑处理器数量(请记住,操作系统本身可能在虚拟机内运行,并且存在 SMT 等硬件技巧),并且您的线程将与同一系统中存在的其他线程。操作系统确实提供了 API 来查询哪些线程/进程当前处于运行状态,哪些线程/进程处于阻塞或就绪但未调度状态,否则编写像 top 这样的程序将会出现问题。

显式设置线程优先级可能会影响操作系统的选择并增加并行执行的线程的平均数量。请注意,如果不加思考地使用它可能会有所帮助,也可能会造成伤害。不过,只要还有其他进程,在多任务操作系统中它就永远不会严格等于 4。确保 100% 的 CPU 硬件在 100% 的时间专用于您的线程的唯一方法是在任何虚拟机管理程序之外的任何操作系统之外运行准系统应用程序(即使如此,也有一些特殊性,请参阅“Intel 系统管理模式”) ”)。

在一个大部分空闲的通用操作系统中,如果您的线程是计算密集型的,我猜平均并行利用率将是 3.9 - 4.0。但只要有一点点的扰动——所有的赌注都会落空。

关于multithreading - 每个核心有多少个线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48723813/

相关文章:

python - 在 Python 中使用带线程的全局字典

c++ - 使用protobuf进行线程通信

java - Object类引用如何接收原始类型数组基地址?

ios - 有什么方法可以断开或结束 ios 中的调用(Swift 或 Objective-C)

方法内的Java空 block 与其他 block 不同?

c++ - 在 C++ 中跨文件行并行化函数的惯用方法

Python 线程返回值

c++ - 段错误(核心转储)只有更大的输入

c - 根据代码块分段核心转储调试它在第 120 行我的链表堆栈实现有问题吗

c# - 如何从 gui 线程更改为后台线程?