每个核心有多少个线程?

How many threads per 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);
   }

}

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

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

可能会对线程数施加唯一限制

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

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

在大部分闲置的通用 OS 中,如果您的线程是计算密集型的,我猜平均并行利用率为 3.9 - 4.0。但是最轻微的扰动——所有的赌注都被取消了。