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

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

XUbuntu 14.04,2 个处理器。

多线程0.8s,单线程0.4s

如果定义了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:%d\n",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:%d\n",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:%fs\n",((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
...

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

即使您重写多线程代码以先生成所有数字然后使用它们,它也会变慢,因为那将与单线程代码完全相同 plus 信号和上下文切换。