为什么使用 pthread 的 Ubuntu 中的单线程比多线程快

why single thread is faster than multithread in Ubuntu using pthread?

本文关键字:单线程 多线程 Ubuntu pthread 为什么      更新时间:2023-10-16

XUbuntu 14.04,2 个处理器。

多线程成本为 0.8 秒,而单线程成本仅为 0.4 秒。

如果定义了MULTI_THREAD,则程序将在单个线程中运行。否则,它是一个多线程程序

怎么了?

 ----------------code------------------------------
    #include <pthread.h>
    #include <semaphore.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #define MULTI_THREAD
    #define NUM             10000
    #define SEM_M           10
    int arr[NUM];
    FILE *f;
        typedef struct _SemData{
            sem_t           sem_full;
            sem_t           sem_empty;
        }SemData;
        void InitSemData(SemData *sd){
            sem_init(&sd->sem_full,0,0);
            sem_init(&sd->sem_empty,0,SEM_M);
        }
        void DestroySemData(SemData *sd){
                sem_destroy(&sd->sem_full);
                sem_destroy(&sd->sem_empty);
            }
            void *Produce(void* data){
            #ifdef MULTI_THREAD
                SemData* psd=(SemData*)data;
            #endif
                int i;
                for(i=0;i<NUM;++i){
            #ifdef MULTI_THREAD
                    sem_wait(&psd->sem_empty);
            #endif
                        arr[i]=i;
                        fprintf(f,"produce:%dn",arr[i]);
            #ifdef MULTI_THREAD
                    sem_post(&psd->sem_full);
            #endif
                }
            }
        void *Custom(void* data){
        #ifdef MULTI_THREAD
            SemData* psd=(SemData*)data;
        #endif
            int i,j;
            for(i=0;i<NUM;++i){
        #ifdef MULTI_THREAD
                sem_wait(&psd->sem_full);
        #endif
                    int tmp=0;
                    for(j=0;j<NUM;++j){
                        tmp+=arr[i];
                    }
                    arr[i]=tmp;
                    fprintf(f,"Custom:%dn",arr[i]);
        #ifdef MULTI_THREAD
                sem_post(&psd->sem_empty);
        #endif
            }
        }
        void main(){
            f=fopen("b.txt","w");
            clock_t start=clock();
        #ifdef MULTI_THREAD
            SemData sd;
            InitSemData(&sd);
            pthread_t th0,th1;
            pthread_create(&th0,NULL,Produce,(void*)&sd);
            pthread_create(&th1,NULL,Custom,(void*)&sd);
            pthread_join(th0,NULL);
            pthread_join(th1,NULL);
            DestroySemData(&sd);
        #else
            Produce(NULL);
            Custom(NULL);
        #endif
            printf("TotalTime:%fsn",((float)(clock()-start))/CLOCKS_PER_SEC);
            fclose(f);
        }
通常,

并行化会带来额外的成本。您必须进行通信才能分发和收集数据。此外,同步可能非常昂贵。

您的单线程代码的工作方式如下:

  1. 生成所有数字
  2. 消耗所有数字

多线程代码的工作方式如下:

Producer                             Consumer
--------                             --------
Produce one number                   Wait for a number to be produced
Wait for a number to be consumed     Consume one number
Produce one number                   Wait for a number to be produced
Wait for a number to be consumed     Consume one number
Produce one number                   Wait for a number to be produced
Wait for a number to be consumed     Consume one number
...

如您所见,一次只有一个线程实际上在执行任何操作。
如果没有信令和上下文切换的开销,这将花费与单线程代码大致相同的时间,但由于信号和上下文切换非常昂贵,因此速度要慢得多。

即使你重写了多线程代码,首先生成所有数字,然后使用它们,它也会更慢,因为这与单线程代码加上信号和上下文切换完全相同。

您正在测试的算法不需要在多个线程中被破坏以提高效率:您必须考虑到创建新线程总是有开销(即分配一些资源、等待同步等)。您必须评估新线程创建开销和单线程复杂性之间的权衡。