• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 200, comments - 8, trackbacks - 0, articles - 0

            實(shí)驗(yàn)環(huán)境:

            CPU: 雙核 Intel(R) Xeon(R) CPU 5130  @ 2.00GHz,內(nèi)存:1G
            系統(tǒng):Red Hat Enterprise Linux ES release 4 (Nahant Update 4)
            內(nèi)核:2.6.9-42.ELsmp

            實(shí)驗(yàn)程序:

            singlethread.c

            1. #include <stdio.h>
            2. #include <sys/types.h>
            3. #include <sys/time.h>
            4. #include <pthread.h>
            5. #include <unistd.h>

            6. #define ORANGE_MAX_VALUE 1000000
            7. #define APPLE_MAX_VALUE 100000000
            8. #define MSECOND 1000000

            9. struct apple
            10. {
            11.     unsigned long long a;
            12.     unsigned long long b;
            13. };

            14. struct orange
            15. {
            16.     int a[ORANGE_MAX_VALUE];
            17.     int b[ORANGE_MAX_VALUE];
            18. };

            19. int main()
            20. {
            21.     struct apple test;
            22.     struct orange test1={{0},{0}};
            23.     
            24.     unsigned long long sum=0,index=0;
            25.     struct timeval tpstart,tpend;
            26.     float timeuse;
            27.     
            28.     test.a=0;
            29.     test.b=0;
            30.         
            31.     gettimeofday(&tpstart,NULL);
            32.     
            33.     for(sum=0;sum<APPLE_MAX_VALUE;sum++)
            34.     {
            35.         test.a+=sum;
            36.         test.b+=sum;
            37.     }
            38.     
            39.     sum=0;
            40.     for(index=0;index<ORANGE_MAX_VALUE;index++)
            41.     {
            42.         sum+=test1.a[index]+test1.b[index];
            43.     }
            44.     
            45.     gettimeofday(&tpend,NULL);
            46.     
            47.     timeuse=MSECOND*(tpend.tv_sec-tpstart.tv_sec)+tpend.tv_usec-tpstart.tv_usec;
            48.     timeuse/=MSECOND;
            49.     printf("main thread Used Time:%f\n",timeuse); 
            50.     
            51.   printf("a = %llu,b = %llu,sum=%llu\n",test.a,test.b,sum);
            52.     
            53.   return 0;
            54. }
            dualrhread.c
            1. #include <sys/time.h>
            2. #include <pthread.h>


            3. #include<stdlib.h>
            4. #include<stdio.h>
            5. #include<sys/types.h>
            6. #include<sys/sysinfo.h>
            7. #include<unistd.h>

            8. #define __USE_GNU
            9. #include<sched.h>
            10. #include<ctype.h>
            11. #include<string.h> 

            12. #include <sys/syscall.h> /*此頭必須帶上*/

            13. pid_t gettid()
            14. {
            15.     return syscall(SYS_gettid);
            16. }


            17. #define ORANGE_MAX_VALUE 1000000
            18. #define APPLE_MAX_VALUE 100000000
            19. #define MSECOND 1000000

            20. struct apple
            21. {
            22.     unsigned long long a;
            23.     unsigned long long b;
            24. };

            25. struct orange
            26. {
            27.     int a[ORANGE_MAX_VALUE];
            28.     int b[ORANGE_MAX_VALUE];
            29. };

            30. struct apple test;
            31. struct orange test1;

            32. int cpu_nums;
            33. cpu_set_t mask;
            34. //cpu_set_t get;
            35.      
            36. inline int set_cpu(int i)
            37. {
            38.     __CPU_ZERO(&mask);
            39.     
            40.     if(<= cpu_nums)
            41.     {
            42.         __CPU_SET(i,&mask);
            43.         
            44.         if(-== sched_setaffinity(gettid(),sizeof(&mask),&mask))
            45.         {
            46.             return -1;
            47.         }
            48.     }
            49.     return 0;
            50. }

            51. void* add(void* x)
            52. {
            53.     int i;    
            54.     if(-== set_cpu(1))
            55.     {
            56.         return NULL;
            57.     } 
            58. /*    
            59.     __CPU_ZERO(&get);
            60.     if (sched_getaffinity(0, sizeof(get), &get) == -1)//獲取線程CPU親和力
            61.     {
            62.         printf("warning: cound not get thread affinity, continuing...\n");
            63.     }
            64.     
            65.     for (= 0; i < 2; i++)
            66.     {
            67.         if (__CPU_ISSET(i, &get))//判斷線程與哪個CPU有親和力
            68.         {
            69.             printf("this thread %d is running processor : %d\n", i,i);
            70.         }
            71.     }
            72. */ 
            73.     unsigned long long sum=0,index=0;    
            74.     for(sum=0;sum<APPLE_MAX_VALUE;sum++)
            75.     {
            76.         ((struct apple *)x)->+= sum;
            77.         ((struct apple *)x)->+= sum;    
            78.     }
            79.         
            80.     return NULL;
            81. }
            82.     
            83. int main () 
            84. {
            85.     
            86.     pthread_t ThreadA;
            87.     unsigned long long sum=0,index=0;
            88.     struct timeval tpstart,tpend;
            89.     float timeuse;
            90.     int i;
            91.     
            92.     test.a=0;
            93.     test.b=0;
            94.     
            95.     cpu_nums = sysconf(_SC_NPROCESSORS_CONF);
            96.     
            97.     if(-== set_cpu(0))
            98.     {
            99.         return -1;
            100.     } 
            101.     
            102.     gettimeofday(&tpstart,NULL);
            103.         
            104.     pthread_create(&ThreadA,NULL,add,&test);
            105.     
            106. /*
            107.     __CPU_ZERO(&get);
            108.     if (sched_getaffinity(0, sizeof(get), &get) == -1)//獲取線程CPU親和力
            109.     {
            110.         printf("warning: cound not get thread affinity, continuing...\n");
            111.     }
            112.     
            113.     for (= 0; i < 2; i++)
            114.     {
            115.         if (__CPU_ISSET(i, &get))//判斷線程與哪個CPU有親和力
            116.         {
            117.             printf("this thread %d is running processor : %d\n", i,i);
            118.         }
            119.     }    
            120. */
            121.     for(index=0;index<ORANGE_MAX_VALUE;index++)
            122.     {
            123.         sum += test1.a[index]+test1.b[index];
            124.     }        
            125.    
            126.     pthread_join(ThreadA,NULL);

            127.     gettimeofday(&tpend,NULL);
            128.     
            129.     timeuse=MSECOND*(tpend.tv_sec-tpstart.tv_sec)+tpend.tv_usec-tpstart.tv_usec;
            130.     timeuse/=MSECOND;
            131.     printf("dual thread Used Time:%f\n",timeuse); 
            132.     
            133.     printf("a = %llu,b = %llu,sum=%llu\n",test.a,test.b,sum);
            134.     
            135.     return 0;
            136. }
            threethread.c
            1. #include <sys/time.h>
            2. #include <pthread.h>

            3. #include<stdlib.h>
            4. #include<stdio.h>
            5. #include<sys/types.h>
            6. #include<sys/sysinfo.h>
            7. #include<unistd.h>

            8. #define __USE_GNU
            9. #include<sched.h>
            10. #include<ctype.h>
            11. #include<string.h> 

            12. #include <sys/syscall.h> /*此頭必須帶上*/

            13. pid_t gettid()
            14. {
            15.     return syscall(SYS_gettid); 
            16. }

            17. #define ORANGE_MAX_VALUE 1000000
            18. #define APPLE_MAX_VALUE 100000000
            19. #define MSECOND 1000000

            20. struct apple
            21. {
            22.     unsigned long long a;
            23.     //char c[128]; /*32,64,128*/
            24.     unsigned long long b;
            25.     //pthread_rwlock_t rwLock;
            26. };

            27. struct orange
            28. {
            29.     int a[ORANGE_MAX_VALUE];
            30.     int b[ORANGE_MAX_VALUE];
            31. };

            32. struct apple test;
            33. struct orange test1;

            34. int cpu_nums;
            35. cpu_set_t mask;
            36.      
            37. inline int set_cpu(int i)
            38. {
            39.     __CPU_ZERO(&mask);
            40.     
            41.     if(<= cpu_nums)
            42.     {
            43.         __CPU_SET(i,&mask);
            44.         
            45.         if(-== sched_setaffinity(gettid(),sizeof(&mask),&mask))
            46.         {
            47.             return -1;
            48.         }
            49.     }
            50.     return 0;
            51. }

            52. void* addx(void* x)
            53. {
            54. /*
            55.     if(-== set_cpu(0))
            56.     {
            57.         return NULL;
            58.     }
            59. */ 
            60.     unsigned long long sum=0,index=0;
            61.     //pthread_rwlock_wrlock(&((struct apple *)x)->rwLock);
            62.     for(sum=0;sum<APPLE_MAX_VALUE;sum++)
            63.     {
            64.         ((struct apple *)x)->+= sum;
            65.     }
            66.     //pthread_rwlock_unlock(&((struct apple *)x)->rwLock);
            67.     
            68.     return NULL;
            69. }

            70. void* addy(void* y)
            71. {
            72. /*  
            73.   if(-== set_cpu(1))
            74.     {
            75.         return NULL;
            76.     }
            77. */ 
            78.     unsigned long long sum=0,index=0;
            79.     //pthread_rwlock_wrlock(&((struct apple *)y)->rwLock);
            80.     for(sum=0;sum<APPLE_MAX_VALUE;sum++)
            81.     {
            82.         ((struct apple *)y)->+= sum;
            83.     }
            84.     //pthread_rwlock_unlock(&((struct apple *)y)->rwLock);
            85.     
            86.     return NULL;
            87. }

            88. int main () 
            89. {
            90.     pthread_t ThreadA,ThreadB;
            91.     unsigned long long sum=0,index=0;
            92.     struct timeval tpstart,tpend;
            93.     float timeuse;
            94. /*    
            95.     cpu_nums = sysconf(_SC_NPROCESSORS_CONF);
            96.     
            97.     if(-== set_cpu(0))
            98.     {
            99.         return -1;
            100.     } 
            101.  */   
            102.     gettimeofday(&tpstart,NULL);
            103.     
            104.     pthread_create(&ThreadA,NULL,addx,&test);
            105.     pthread_create(&ThreadB,NULL,addy,&test);

            106.     for(index=0;index<ORANGE_MAX_VALUE;index++)
            107.     {
            108.         sum+=test1.a[index]+test1.b[index];
            109.     }
            110.     
            111.     pthread_join(ThreadA,NULL);
            112.     pthread_join(ThreadB,NULL);
            113.     
            114.     gettimeofday(&tpend,NULL);
            115.     
            116.     timeuse=MSECOND*(tpend.tv_sec-tpstart.tv_sec)+tpend.tv_usec-tpstart.tv_usec;
            117.     timeuse/=MSECOND;
            118.     printf("thread thread,Used Time:%f\n",timeuse); 
            119.     
            120.     printf("a = %llu,b = %llu,sum=%llu\n",test.a,test.b,sum);
            121.   
            122.     return 0;
            123. }
            本文采用采用 gettimeofday() 來獲取系統(tǒng)時鐘(system clock)時間,可以精確到微秒。
            本文平均值算法采用的是去掉一個最大值去掉一個最小值,然后平均

            一、單核 單、多線程效率比較

            單核

             

            1

            2

            3

            4

            5

            6

            7

            8

            9

            10

            平均

            單線程

            0.951274

            0.951883

            0.951347

            0.950893

            0.810648

            0.810705

            0.951196

            0.951343

            0.811413

            0.950892

            0,916133

            雙線程

            0.989287

            0.986391

            0.986576

            0.985043

            0.986335

            0.985320

            0.986790

            0.986837

            0.985602

            0.986535

            0.986298

            三線程加鎖

            1.318721

            1.318701

            1.319036

            1.318652

            1.318614

            1.318923

            1.318636

            1.318687

            1.319026

            1.318933

            1.318785

            三線程不加鎖

            1.318658

            1.318766

            1.318570

            1.318894

            1.318588

            1.318658

            1.318958

            1.318709

            1.318689

            1.319020

            1.318740



            為什么多線程會比單線程更耗時呢?其原因就在于,線程啟停以及線程上下文切換都會引起額外的開銷,所以消耗的時間比單線程多。


            二、雙核---單線程、多線程、優(yōu)化后多線程效率比較

            雙核三線程不加鎖

             

            1

            2

            3

            4

            5

            6

            7

            8

            9

            10

            Best

            單線程

            0.947490

            0.948153

            0.950648

            0.950412

            0.950422

            0.950407

            0.810345

            0.950386

            0.947501

            0.947513

            0.949036

             

            雙線程

            0.983432

            0.980912

            0.976860

            0.975621

            0.976582

            0.978240

            0.975736

            0.981523

            0.979724

            0.981337

            0.978864

             

            三線程加鎖

            1.310762

            1.309590

            1.308914

            1.309287

            1.310924

            1.310837

            1.307147

            1.311698

            1.311861

            1.309007

            1.310127

            三線程不加鎖

            1.431863

            1.422951

            1.472916

            1.482321

            1.477823

            1.477272

            1.423854

            1.423412

            1.422267

            1.423243

            1.444167

            三線程加鎖Cache32

            1.310174

            1.308985

            1.311462

            1.311574

            1.309590

            1.311329

            1.311602

            1.311154

            1.307573

            1.310447

            1.310589

            三線程不加鎖Cache32

            0.664234

            0.664244

            0.664186

            0.664264

            0.664317

            0.664234

            0.662658

            0.662176

            0.662164

            0.662159

            0.663520


            為什么三線程不加鎖比三線程加鎖還慢呢?
            當(dāng)兩個線程寫入同一個 cache 的不同部分時,會互相競爭該 cache 行,也就是寫后寫的問題。下文會詳細(xì)分析。
            為什么三線程加鎖Cache32比三線程不加鎖Cache32比慢幾乎一倍呢?
            其原因也很簡單,那把讀寫鎖就是罪魁禍?zhǔn)住?shí)際情況并不是并行執(zhí)行,反而成了串行執(zhí)行。

            三、針對 Cache 的優(yōu)化

            在串行程序設(shè)計過程中,為了節(jié)約帶寬或者存儲空間,比較直接的方法,就是對數(shù)據(jù)結(jié)構(gòu)做一些針對性的設(shè)計,將數(shù)據(jù)壓縮 (pack) 的更緊湊,減少數(shù)據(jù)的移動,以此來提高程序的性能。但在多核多線程程序中,這種方法往往有時會適得其反。

            數(shù)據(jù)不僅在執(zhí)行核和存儲器之間移動,還會在執(zhí)行核之間傳輸。根據(jù)數(shù)據(jù)相關(guān)性,其中有兩種讀寫模式會涉及到數(shù)據(jù)的移動:寫后讀和寫后寫 ,因?yàn)檫@兩種模式會引發(fā)數(shù)據(jù)的競爭,表面上是并行執(zhí)行,但實(shí)際只能串行執(zhí)行,進(jìn)而影響到性能。

            處理器交換的最小單元是 cache 行,或稱 cache 塊。在多核體系中,對于不共享 cache 的架構(gòu)來說,兩個獨(dú)立的 cache 在需要讀取同一 cache 行時,會共享該 cache 行,如果在其中一個 cache 中,該 cache 行被寫入,而在另一個 cache 中該 cache 行被讀取,那么即使讀寫的地址不相交,也需要在這兩個 cache 之間移動數(shù)據(jù),這就被稱為 cache 偽共享,導(dǎo)致執(zhí)行核必須在存儲總線上來回傳遞這個 cache 行,這種現(xiàn)象被稱為“乒乓效應(yīng)”。

            同樣地,當(dāng)兩個線程寫入同一個 cache 的不同部分時,也會互相競爭該 cache 行,也就是寫后寫的問題。上文曾提到,不加鎖的方案反而比加鎖的方案更慢,就是互相競爭 cache 的原因。

            在 X86 機(jī)器上,某些處理器的一個 cache 行是64字節(jié),具體可以參看 Intel 的參考手冊。

            既然不加鎖三線程方案的瓶頸在于 cache,那么讓 apple 的兩個成員 a 和 b 位于不同的 cache 行中,效率會有所提高嗎?

            修改后的代碼片斷如下:

            1. struct apple
            2. {
            3.     unsigned long long a;
            4.     char c[128]; /*32,64,128*/
            5.     unsigned long long b;
            6. };
            小小的一行代碼,盡然帶來了如此高的收益,不難看出,我們是用空間來換時間。當(dāng)然讀者也可以采用更簡便的方法: __attribute__((__aligned__(L1_CACHE_BYTES))) 來確定 cache 的大小。

            參考http://www.ibm.com/developerworks/cn/linux/l-cn-optimization/index.html

            轉(zhuǎn)自:http://blog.chinaunix.net/uid-20556054-id-3070826.html
            日韩人妻无码一区二区三区久久99| 精品国产99久久久久久麻豆| 精品乱码久久久久久夜夜嗨| 亚洲国产综合久久天堂| 日韩精品久久无码人妻中文字幕| 久久91精品国产91久久麻豆| 亚洲AⅤ优女AV综合久久久| 久久精品国产99久久无毒不卡| 狠狠色综合久久久久尤物| 少妇久久久久久被弄高潮| 久久99精品久久久久久齐齐| 久久精品中文闷骚内射| 欧美一区二区久久精品| 91精品国产高清久久久久久91| 久久午夜夜伦鲁鲁片免费无码影视 | 国产午夜福利精品久久2021| 久久亚洲精品无码播放| 国产精品免费福利久久| 无码任你躁久久久久久老妇App| 91麻精品国产91久久久久| 蜜臀av性久久久久蜜臀aⅴ麻豆| 久久强奷乱码老熟女网站| 99久久国产综合精品五月天喷水| 久久棈精品久久久久久噜噜| 欧美一级久久久久久久大片| 国内精品久久久久久久影视麻豆 | 色噜噜狠狠先锋影音久久| 久久综合给合久久狠狠狠97色| 精品伊人久久久| 亚洲国产精品无码久久青草| 热RE99久久精品国产66热| 国产无套内射久久久国产| 中文字幕成人精品久久不卡| 国内精品伊人久久久久| 国产精品久久久久影视不卡| 久久青草国产精品一区| 久久精品人人做人人爽电影| 激情久久久久久久久久| 久久影院久久香蕉国产线看观看| 三级片免费观看久久| 中文精品久久久久人妻|