亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 24719814 | 回復: 24719814
打印 上一主題 下一主題

[C] 【最終版 & 總結】自實現(xiàn)自旋鎖 與 mutex,spinlock比較(結果令人吃驚) [復制鏈接]

論壇徽章:
0
跳轉到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2011-07-29 11:39 |只看該作者 |倒序瀏覽
本帖最后由 ydfgic 于 2011-08-01 13:58 編輯

總結一下:
最后修改了一下測試代碼,比較方便的設置線程數(shù),選擇測試對象,設置delay的參數(shù)。
經(jīng)過測試發(fā)現(xiàn)我的實現(xiàn)測試的結果時間非常穩(wěn)定,2個,10個,20個乃至40個線程的差別很小,幾乎達到了與線程數(shù)無關,同樣mutex也是和線程數(shù)關系不大,但是pthread_spinlock_t對線程數(shù)敏感,線程多的情況下,效率會降低很多。
同樣增加加鎖的粒度,對測試結果也有影響,當粒度很小的情況下,我的實現(xiàn)是mutex的4-5倍快,但是粒度很大的情況,比如我設置到delay的循環(huán)次數(shù)為1000時,效率是mutex的兩倍多快,但是cpu更忙些。spinlock的速度就不提了,很低。
結論:
如果是比較大粒度的加鎖肯定是mutex首選,雖然性能中庸,但是它因為會休眠掛起,不占用cpu,對系統(tǒng)影響小。
如果是比較細粒度的加鎖可以用我實現(xiàn)的lock,對線程數(shù)量幾乎無關,效率極高,可能是因為實現(xiàn)簡單,最大效率的做到了切換cpu,保證一個線程執(zhí)行,減少了多余環(huán)節(jié)。
pthread_spinlock_t的局限性太大,如果線程多的情況下,會造成性能的很大程度的損失。同時還僅限于小粒度的加鎖情況。

給出測試數(shù)據(jù):
1)20線程,0delay
我的:time ./myspinlock_O3.out 20 0 0
real    0m0.323s
user    0m0.364s
sys     0m0.276s

mutex:time ./myspinlock_O3.out 20 1 0
real    0m1.634s
user    0m1.972s
sys     0m1.264s

spinlock: time ./myspinlock_O3.out 20 2 0
real    0m6.259s
user    0m12.477s
sys     0m0.004s

2)20線程,100 delay
我的:time ./myspinlock_O3.out 20 0 100
real    0m2.965s
user    0m3.268s
sys     0m2.636s

mutex:time ./myspinlock_O3.out 20 1 100
real    0m6.493s
user    0m6.344s
sys     0m6.604s

spinlock: time ./myspinlock_O3.out 20 2 100
real    0m15.760s
user    0m31.378s
sys     0m0.004s

3)10線程,0delay
我的:time ./myspinlock_O3.out 10 0 0
real    0m0.318s
user    0m0.372s
sys     0m0.248s
mutex:time ./myspinlock_O3.out 10 1 0
real    0m1.511s
user    0m1.808s
sys     0m1.200s
spinlock:time ./myspinlock_O3.out 10 2 0
real    0m3.625s
user    0m7.224s
sys     0m0.004s

4)2線程,0delay
我的:time ./myspinlock_O3.out 2 0 0
real    0m0.323s
user    0m0.376s
sys     0m0.184s
mutex:time ./myspinlock_O3.out 2 1 0
real    0m1.453s
user    0m1.688s
sys     0m1.136s
spinlock:time ./myspinlock_O3.out 2 2 0
real    0m0.819s
user    0m1.624s
sys     0m0.004s


最終版的實現(xiàn)
  1. #include<stdint.h>
  2. #include<unistd.h>

  3. typedef volatile uint32_t spinlock_t;

  4. #define MY_SPINLOCK_INITIALIZER 0

  5. #define spinlock_lock(lock) do{  \
  6.     while(!__sync_bool_compare_and_swap(lock, 0, 1))    \
  7.         sched_yield();  \
  8. }while(0)

  9. #define spinlock_unlock(lock) do{    \
  10.     *lock = 0;  \
  11. }while(0)
復制代碼
最終版的測試代碼
  1. #include"myspinlock.h"

  2. // gcc -Wall -g -O3 -o myspinlock.out myspinlock.c -lpthread


  3. /////////////////////////                test  

  4. my_spinlock_t lock =  MY_SPINLOCK_INITIALIZER;
  5. volatile int cnt = 0;

  6. #include<pthread.h>
  7. #include<stdio.h>
  8. #include <stdlib.h>

  9. #define  TOTAL 1000000 * 20
  10. int NR;
  11. int DELAY_CNT = 100;

  12. void * fun1(void * arg)
  13. {
  14.         int i = 0, id = *(int*)arg;
  15.         printf("thread:%d\n",id);
  16.         for(; i < NR; i++)
  17.         {
  18.                 spinlock_lock(&lock);
  19.                 cnt++;
  20.                 int j = 0;
  21.                 for (; j < DELAY_CNT; j++) {
  22.                         *foo = (*foo * 33) + 17;
  23.                 }
  24.                 spinlock_unlock(&lock);
  25.         }
  26.         printf("thread:%d over, lock:%d\n",id, lock);
  27.         return 0;
  28. }

  29. pthread_mutex_t mlock = PTHREAD_MUTEX_INITIALIZER;

  30. void * fun2(void * arg)
  31. {
  32.         int i = 0, id = *(int*)arg;
  33.         printf("thread:%d\n",id);
  34.         for(; i < NR; i++)
  35.         {
  36.                 pthread_mutex_lock(&mlock);
  37.                 cnt++;
  38.                 int j = 0;
  39.                 for (; j < DELAY_CNT; j++) {
  40.                         *foo = (*foo * 33) + 17;
  41.                 }
  42.                 pthread_mutex_unlock(&mlock);
  43.         }
  44.         printf("thread:%d over, lock:%d\n",id, lock);
  45.         return 0;
  46. }

  47. pthread_spinlock_t splock;

  48. void * fun3(void * arg)
  49. {
  50.         int i = 0, id = *(int*)arg;
  51.         printf("thread:%d\n",id);
  52.         for(; i < NR; i++)
  53.         {
  54.                 pthread_spin_lock(&splock);
  55.                 cnt++;
  56.                 int j = 0;
  57.                 for (; j < DELAY_CNT; j++) {
  58.                         *foo = (*foo * 33) + 17;
  59.                 }
  60.                 pthread_spin_unlock(&splock);
  61.         }
  62.         printf("thread:%d over, lock:%d\n",id, lock);
  63.         return 0;
  64. }

  65. int N = 20;
  66. int main(int c, char * s[])
  67. {
  68.         int which = 0;
  69.         if(c > 1)
  70.         {
  71.                 //線程數(shù)
  72.                 N = atoi(s[1]);
  73.                 if(N > 20 || N <= 1) N = 10;
  74.         }
  75.         if(c > 2)
  76.         {
  77.                 //which func?
  78.                 which = atoi(s[2]);
  79.                 if(which > 2 || which < 0) which = 0;
  80.         }
  81.         if(c > 3)
  82.         {
  83.                 //delay param
  84.                 DELAY_CNT = atoi(s[3]);
  85.                 if(DELAY_CNT > 10000 || DELAY_CNT < 0) DELAY_CNT= 100;
  86.         }

  87.         pthread_t id[N];
  88.         int args[N];
  89.         int i = 0;
  90.         void * (*fun[])(void*) = { fun1,fun2,fun3};
  91.         pthread_spin_init(&splock,0);
  92.         NR = TOTAL / N;

  93.         for(;i<N;++i){
  94.                 args[i] = i;
  95.                 pthread_create(&id[i],NULL,fun[which],&args[i]);
  96.         }

  97.         for(i=0;i<N;++i){
  98.                 printf("join thread:%d\n", i);
  99.                 pthread_join(id[i],NULL);
  100.                 printf("join thread:%d done\n", i);
  101.         }

  102.         printf("cnt = %d, should be %d\n",cnt, N * NR);
  103.         return 0;
  104. }
復制代碼
===============================================
先前的更新僅僅做為參考

更新
重新修改了我的實現(xiàn),加入了放棄時間片的情況,測試結果,幾乎是mutex的2-3倍效率
real    0m0.431s
user    0m0.604s
sys     0m0.240s

我想這個應該就會是我理想中的最終版本了,起碼可以拋棄 pthread 庫的mutex實現(xiàn)一些簡單的加鎖的功能。

代碼:
  1. #ifndef MY_SPINLOCK_H
  2. #define MY_SPINLOCK_H

  3. #include<stdint.h>
  4. #include<unistd.h>

  5. typedef volatile uint32_t my_spinlock_t;

  6. #define MY_SPINLOCK_INITIALIZER 0
  7. #define DELAY_NR 10000

  8. static uint32_t bar = 13;
  9. static uint32_t *foo = &bar;

  10. #define do_hash(a) do{  \
  11. (a) = ((a)+0x7ed55d16) + ((a)<<12); \
  12. (a) = ((a)^0xc761c23c) ^ ((a)>>19); \
  13. (a) = ((a)+0x165667b1) + ((a)<<5);  \
  14. (a) = ((a)+0xd3a2646c) ^ ((a)<<9);  \
  15. (a) = ((a)+0xfd7046c5) + ((a)<<3);  \
  16. (a) = ((a)^0xb55a4f09) ^ ((a)>>16); \
  17. }while(0)

  18. #define my_spinlock_lock(lock) do{  \
  19.     while(!__sync_bool_compare_and_swap(lock, 0, 1))    \
  20.     {   \
  21.         while(*lock)    \
  22.         {   \
  23.             do_hash(*foo);  \
  24.             if((*foo % 11) == 1)    \
  25.                 sched_yield();  \
  26.         }   \
  27.     }   \
  28. }while(0)

  29. #define my_spinlock_unlock(lock) do{    \
  30.     *lock = 0;  \
  31. }while(0)

  32. #endif
復制代碼
=======================================

最近在研究原子操作,按網(wǎng)上一些資料實現(xiàn)了個自旋鎖
拿來和 posix 的mutex,spinlock 一起測,結果出乎我意料。
mutex的成績非常好,我自己實現(xiàn)的稍微差點,posix 的pthread_spinlock_t的結果比較差。
這個真沒想到,mutex的效率這么高,看到這個結果我都覺得不相信自己的眼睛了
還是印證了,不要靠自己感覺,實際數(shù)據(jù)才是最真實的。

誰能解釋一下,謝謝~

環(huán)境:
uname -a
Linux bsd02 2.6.35.9 #1 SMP Tue Jan 11 02:09:50 EST 2011 x86_64 GNU/Linux
雙核 Pentium(R) Dual-Core  CPU      E5400  @ 2.70GHz

并發(fā)20個線程測試,結果:
我的實現(xiàn):
real    0m1.659s
user    0m3.276s
sys     0m0.000s

mutex:
real    0m1.481s
user    0m1.164s
sys     0m1.764s

pthread spinlock:
real    0m6.171s
user    0m12.301s
sys     0m0.004s

論壇徽章:
0
2 [報告]
發(fā)表于 2011-07-29 11:43 |只看該作者
spinlock有這么差嗎?是不是沒用對

論壇徽章:
0
3 [報告]
發(fā)表于 2011-07-29 11:45 |只看該作者
本帖最后由 ydfgic 于 2011-08-01 10:45 編輯

這是最原始版本的代碼,最終代碼1樓以更新
======
附上代碼:
  1. #ifndef MY_SPINLOCK_H
  2. #define MY_SPINLOCK_H

  3. #include<stdint.h>

  4. typedef volatile uint32_t my_spinlock_t;

  5. #define MY_SPINLOCK_INITIALIZER 0
  6. #define DELAY_NR 10000

  7. static uint32_t bar = 13;
  8. static uint32_t *foo = &bar;

  9. #define my_spinlock_lock(lock) do{  \
  10.     int i;  \
  11.     while(!__sync_bool_compare_and_swap(lock, 0, 1))    \
  12.     {   \
  13.         i = 0;  \
  14.         while(i++ < DELAY_NR)   \
  15.             *foo = (*foo * 33) + 17;    \
  16.     }   \
  17. }while(0)

  18. #define my_spinlock_unlock(lock) do{    \
  19.     *lock = 0;  \
  20. }while(0)


  21. #endif
復制代碼
  1. #include"myspinlock.h"
  2. my_spinlock_t lock =  MY_SPINLOCK_INITIALIZER;
  3. volatile int cnt = 0;

  4. #include<pthread.h>
  5. #include<stdio.h>
  6. // gcc -Wall -g -o myspinlock.out myspinlock.c -lpthread

  7. #define  NR 1000000

  8. void * fun1(void * arg)
  9. {
  10.     int i = 0, id = *(int*)arg;
  11.     printf("thread:%d\n",id);
  12.     for(; i < NR; i++)
  13.     {
  14.         my_spinlock_lock(&lock);
  15.         cnt++;
  16.         my_spinlock_unlock(&lock);
  17.     }
  18.     printf("thread:%d over, lock:%d\n",id, lock);
  19.     return 0;
  20. }

  21. pthread_mutex_t mlock = PTHREAD_MUTEX_INITIALIZER;

  22. void * fun2(void * arg)
  23. {
  24.     int i = 0, id = *(int*)arg;
  25.     printf("thread:%d\n",id);
  26.     for(; i < NR; i++)
  27.     {
  28.         pthread_mutex_lock(&mlock);
  29.         cnt++;
  30.         pthread_mutex_unlock(&mlock);
  31.     }
  32.     printf("thread:%d over, lock:%d\n",id, lock);
  33.     return 0;
  34. }
  35. pthread_spinlock_t splock;

  36. void * fun3(void * arg)
  37. {
  38.     int i = 0, id = *(int*)arg;
  39.     printf("thread:%d\n",id);
  40.     for(; i < NR; i++)
  41.     {
  42.         pthread_spin_lock(&splock);
  43.         cnt++;
  44.         pthread_spin_unlock(&splock);
  45.     }
  46.     printf("thread:%d over, lock:%d\n",id, lock);
  47.     return 0;
  48. }

  49. int N = 20;
  50. int main(int c, char * s[])
  51. {
  52.     pthread_t id[N];
  53.     int args[N];
  54.     int i = 0;
  55.     void * (*fun[])(void*) = { fun1,fun2,fun3};
  56.     if(--c > 2) c = 0;
  57.     printf("c:%d\n",c);
  58.     pthread_spin_init(&splock,0);

  59.     for(;i<N;++i){
  60.         args[i] = i;
  61.         pthread_create(&id[i],NULL,fun[c],&args[i]);
  62.     }

  63.     for(i=0;i<N;++i){
  64.         printf("join thread:%d\n", i);
  65.         pthread_join(id[i],NULL);
  66.         printf("join thread:%d done\n", i);
  67.     }

  68.     printf("%d\n",cnt);
  69.     return 0;
  70. }
復制代碼

論壇徽章:
0
4 [報告]
發(fā)表于 2011-07-29 11:47 |只看該作者
回復 2# int-main
我貼代碼了。
spinlock真的很差,這是個奇跡,它就是發(fā)生了。

論壇徽章:
0
5 [報告]
發(fā)表于 2011-07-29 11:58 |只看該作者
最關鍵的__sync_bool_compare_and_swap是什么

你這是每次都lock成功的例子,測試結果沒代表性

論壇徽章:
1
2015年辭舊歲徽章
日期:2015-03-03 16:54:15
6 [報告]
發(fā)表于 2011-07-29 13:05 |只看該作者
spin lock, 翻譯自選鎖不好,要翻譯成 “忙等鎖”,
忙等,必然用在非常變態(tài)的場合。

論壇徽章:
0
7 [報告]
發(fā)表于 2011-07-29 13:12 |只看該作者
最關鍵的__sync_bool_compare_and_swap是什么

你這是每次都lock成功的例子,測試結果沒代表性
deadlylight 發(fā)表于 2011-07-29 11:58



    __sync_bool_compare_and_swap  是 GCC 內建的原子操作函數(shù), 執(zhí)行CAS 操作,也就是 比較如果相等就swap,并且返回true,否則返回false。所以失敗的線程都會進入while循環(huán)里去,忙等。

還有個你注意到?jīng)],posix 的spinlock效率還低下些。

論壇徽章:
0
8 [報告]
發(fā)表于 2011-07-29 13:17 |只看該作者
spin lock, 翻譯自選鎖不好,要翻譯成 “忙等鎖”,
忙等,必然用在非常變態(tài)的場合。
群雄逐鹿中原 發(fā)表于 2011-07-29 13:05



    我覺得我在這里測試的情況也屬于變態(tài),呵呵,就是一個 計數(shù)累加 就放鎖了,按常規(guī)邏輯,這就是用spinlock的場景,防止線程陷落到內核態(tài),應該效率比mutex高很多。但是事實卻相反...所以很不解啊

論壇徽章:
1
2015年辭舊歲徽章
日期:2015-03-03 16:54:15
9 [報告]
發(fā)表于 2011-07-29 13:22 |只看該作者
回復 8# ydfgic


    你的線程,在 while(i++ < DELAY_NR)  時,
被切換掉,然后另一個線程開始自旋,不是要等出人命?

論壇徽章:
0
10 [報告]
發(fā)表于 2011-07-29 13:52 |只看該作者
回復 9# 群雄逐鹿中原


    好像自旋鎖是這個概念吧,不放cpu在那里忙等,我已經(jīng)調整了DELAY_NR的值了
網(wǎng)上還有個變態(tài)的版本就是 while(*lock);  我試過了效率要低些。
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術有限公司. 版權所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關心和支持過ChinaUnix的朋友們 轉載本站內容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP