首页 > 解决方案 > 为什么多线程更慢?

问题描述

实现了使用归并排序的1000000个节点的三个链表的多进程多线程实现。我比较了实现程序的实时性,但是多线程的方式比较慢。这是为什么?

process.c 中的主要方法

    /* Insert nodes */
    Node* tmp = NULL;   
    int num;    
    for( int i = 0; i < MAX; i++ )
    {
        fscanf(fread,"%d",&num);    
        tmp = createNode(num , i ); 
        insertNode( &list1.head, &list1.tail, tmp );
        tmp = createNode(num , i ); 
        insertNode( &list2.head, &list2.tail, tmp );    
        tmp = createNode(num , i );
        insertNode( &list3.head, &list3.tail, tmp );    
        tmp = createNode(num , i ); 
    }
    free( tmp );    
    fclose(fread);  

    if ((t1 = times(&mytms)) == -1) {
        perror("times 1");
        exit(1);
    }

    pid1= fork();   
    if(pid1==0){
        mergeSort( &list1.head );   
        file_output(&list1);    
        freeAll( list1.head );
        exit(1);    
    }
    pid2= fork();   
    if(pid2==0){
        mergeSort( &list2.head );   
        file_output(&list2);    
        freeAll( list2.head );  
        exit(2);    
    }
    pid3 = fork();
    if(pid3==0){
        mergeSort( &list3.head );   
        file_output(&list3);    
        freeAll( list3.head );  
        exit(3);    
    }

    wait(&status);  
    wait(&status);
    wait(&status);

    if ((t2 = times(&mytms)) == -1) {   
        perror("times 2");
        exit(1);
    }

    printf("Real time : %.5f sec\n", (double)(t2 - t1) / CLK_TCK);
    printf("User time : %.5f sec\n", (double)mytms.tms_utime / CLK_TCK);
    printf("System time : %.5f sec\n", (double)mytms.tms_stime / CLK_TCK);

实时结果:1.65

thread.c 中的主要内容

   /* Insert nodes */
   Node* tmp = NULL;   
   int num;           

   for( int i = 0; i < MAX; i++ )
   {
      fscanf(fread,"%d",&num); 
      tmp = createNode(num , i ); 
      insertNode( &list1.head, &list1.tail, tmp );  
      tmp = createNode(num , i );  
      insertNode( &list2.head, &list2.tail, tmp );  
      tmp = createNode(num , i );  
      insertNode( &list3.head, &list3.tail, tmp );  
   }

   free( tmp );
   fclose(fread);  

   if ((t1 = times(&mytms)) == -1) {
        perror("times 1");
        exit(1);
   }

   pthread_create( &t_id1, NULL, thread_func, &list1 );
   pthread_create( &t_id2, NULL, thread_func, &list2 );
   pthread_create( &t_id3, NULL, thread_func, &list3 );

   pthread_join( t_id1, (void*)&status );
   pthread_join( t_id2, (void*)&status );
   pthread_join( t_id3, (void*)&status );

   if ((t2 = times(&mytms)) == -1) {
        perror("times 2");
      exit(1);
   }

   printf("Real time : %.5f sec\n", (double)(t2 - t1) / CLK_TCK);
   printf("User time : %.5f sec\n", (double)mytms.tms_utime / CLK_TCK);  
   printf("System time : %.5f sec\n", (double)mytms.tms_stime / CLK_TCK);  

结果实时 2.27

标签: cmultithreadingtimemultiprocess

解决方案


为什么多线程更慢?

它是特定于处理器的,并且与内核数量、 CPU 缓存的组织、它们的缓存一致性、您的RAM相关。另请参阅https://www.phoronix.com/上的测试和基准测试;在 Intel Core i7 10700K 和 AMD Ryzen 9 3900X(价格接近)上不会一样。

它也是编译器优化特定的。阅读Dragon 的书和一本关于计算机体系结构的好书

它还取决于您特定的操作系统和特定的C 标准库(例如GNU glibcmusl-libc不同),并且可能具有与同一glibc 2.31台计算机不同的性能。阅读高级 Linux 编程pthreads(7)nptl(7)numa(7)time(7)madvise(2)syscalls(2)glibc 2.30

您是否在最近的 Linux 上尝试过至少调用了最近的GCC 10 ? gcc -Wall -O3 -mtune=native

您可以在 Linux 上使用proc(5)然后使用hwinfo来查询您的硬件。

您可能对OpenCLOpenMPOpenACC感兴趣,并且应该阅读有关特定 C 编译器的优化选项的信息。对于最近的GCC,请参阅。您甚至可以使用您的GCC 插件自定义您最近的 GCC以改进优化,您可以尝试最近的Clangicc编译器。

另请参阅MILEPOST GCC项目和CTuning one。另请阅读这份报告草案。参加 ACM SIGPLANSIGOPS会议。联系您附近的计算机科学学者。

您可能可以在理解您的问题的答案的同时获得博士学位。


推荐阅读