青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Kisser Leon

這個kisser不太冷
posts - 100, comments - 102, trackbacks - 0, articles - 0

多線程計算PI碰到的問題

Posted on 2007-03-23 23:42 kk 閱讀(1970) 評論(3)  編輯 收藏 引用 所屬分類: IT

例子如下,用于計算 PI 的值。 gIterations 是計算 PI 的迭代次數, gThreadCount 是線程的個數。方法是這樣子的,把 PI 分成 gThreadCount 個段,分別讓一個線程來執行 PI 的求值操作。求得 PI 值有兩種方法,一種是直接把各個線程每一步所求得的值加到 gSum 上去,另一種是把各個線程所求得的值加到一個與之對應的全局變量中去。對每個線程 i ,輸出 Thread number:I aaaaaaaa ,表示線程開始執行,輸出 Thread number:I bbbbbbb 則表示線程執行完畢。有些地方還可以優化的,不過這里只是為了演示多線程的問題,所以就不予關注了。恩。

代碼如下。當只有一個 thread 的時候,結果是 OK 的( gSum==sum==3.14159* ,用等號有點問題,但是結果差異在十萬分之一以內)。當有三個 threads 的時候,問題就開始出現了! gSum 計算出來只有 2.* !怎么會這樣子呢?各位有興趣的話,可以運行下面的代碼試試看。接著看下面的分析。

#include <windows.h>

#include <stdio.h>

#include <time.h>

?

const int gIterations = 100000000;

const int gThreadCount = 3;

double gSum = 0.0;

double gPart[gThreadCount];

?

DWORD WINAPI threadFunction(LPVOID pArg)

{

??? int threadNum = (int)pArg;//starts from 0

??? printf("Thread number:%d: aaaaaaaaaaaa\n", threadNum);

??? for ( int i=threadNum; i<gIterations; i+=gThreadCount )

??? {

??????? double dx = (i + 0.5f) / gIterations;

??????? gSum += 4.0f / (1.0f + dx*dx);//cause problems here!

??????? gPart[threadNum] += 4.0f / (1.0f + dx*dx);

??? }

?

??? printf("part%d value:%.6f\n", threadNum, gPart[threadNum]/gIterations);

??? printf("Thread number:%d: bbbbbbbbbbbb\n", threadNum);

??? return 0;

}

?

int main()

{

??? memset(gPart, 0.0, sizeof(gPart)/sizeof(double));//init to 0

?

??? printf("Computing value of Pi: \n");

??? clock_t start = clock();

?

??? HANDLE threadHandles[gThreadCount];

??? for ( int i=0; i<gThreadCount; i++ )

??? {

??????? threadHandles[i] = CreateThread( NULL,?????????? // Security attributes

??????? ???????????????????????????????? 0,????????????? // Stack size

??????? ???????????????????????????????? threadFunction, // Thread function

??????? ??? ?????????????????????????????(LPVOID)i, // Data for thread func()

??????? ???????????????????????????????? 0,????????????? // Thread start mode

??????? ???????????????????????????????? NULL);????????? // Returned thread ID

??? }

?

??? WaitForMultipleObjects(gThreadCount, threadHandles, TRUE, INFINITE);

?

??? clock_t finish = clock();

??? printf("Executing time:%d\n", finish-start);

?

??? printf("global: %f\n", gSum / gIterations);

?

??? double sum = 0.0;

??? for(int i=0; i<gThreadCount; i++)

??????? sum += gPart[i];

??? printf("parts: %f\n", sum / gIterations);

?

??? return 0;

}

?

輸出信息:

Computing value of Pi:

Thread number:1: aaaaaaaaaaaa

Thread number:0: aaaaaaaaaaaa

Thread number:2: aaaaaaaaaaaa

part1 value:1.047198

Thread number:1: bbbbbbbbbbbb

part0 value:1.047198

Thread number:0: bbbbbbbbbbbb

part2 value:1.047198

Thread number:2: bbbbbbbbbbbb

Executing time:19109

global: 2.711738

parts: 3.141593

Press any key to continue

以上是輸出信息通過 gSum 求出來的值在 2.7 左右,事實上有的時候還會更低。 WHY ?問題出現在哪里呢?通過各個線程計算出來的值是對的,說明問題不是出現在這里,也就是說問題是出現在線程切換的時候使得 gSum 少加了一些值!什么時候切換會導致這個問題呢?問題出現在下面這一句里面:

??????? gSum += 4.0f / (1.0f + dx*dx);//cause problems here!

這一行等價于:

?????????????????? gSum = gSum + value;

這一行代碼相當于兩行代碼:

???????? temp = gSum + value;

???????? gSum = temp;

如果有兩個線程的話:

線程 A:

1、 ???????????? temp = gSum + value;

2、 ???????????? gSum = temp;

線程 B:

3、 ???????????? temp = gSum + value;

4、 ???????????? gSum = temp;

由于線程切換的任意性,這幾條指令的執行順序有以下幾種可能:

1 2 3 4 1 3 2 4 1 3 4 2 3 1 2 4 3 1 4 2 3 4 1 2

其中 1 3 2 4 順序就是會出錯的,很顯然按照 1 3 2 4 順序的時候 1 中的 value 就沒有被加進來了。這就是問題所在!同樣 1 3 4 2 3 1 2 4 3 1 4 2 都是有問題。

那如何解決這個問題呢?要把 1 2 捆綁在一起作為一個單位操作,即所謂原子操作,要么不執行,要么就全都執行了。

正確的代碼如下。給 gSum+= 操作放到一個 critical section 中,保證此時不會被線程切換干擾。關于 critical section 的詳細信息請參考 MSDN Good luck & have fun.

#include <windows.h>

#include <stdio.h>

?

const int gIterations = 100000;

const int gThreadCount = 4;

double gSum = 0.0;

CRITICAL_SECTION gCS;

?

DWORD WINAPI threadFunction(LPVOIDpArg)

{

???? double partialSum = 0.0;

?

???? for ( inti=(int)pArg+1; i<gIterations; i+=gThreadCount )

???? {

???????? double dx = (i - 0.5f) / gIterations;

???????? partialSum += 4.0f / (1.0f + dx*dx);

???? }

?

???? EnterCriticalSection(&gCS);

???? gSum += partialSum;

???? LeaveCriticalSection(&gCS);

?

???? return 0;

}

?

int main ()

{

???? printf("Computing value of Pi: \n");

?

???? InitializeCriticalSection(&gCS);

???? HANDLE threadHandles[gThreadCount];

???? for ( inti=0; i<gThreadCount; ++i )

???? {

???????? threadHandles[i] = CreateThread( NULL,?????????? // Security attributes

???????? ???????????????????????????????? 0,????????????? // Stack size

???????? ???????????????????????????????? threadFunction, // Thread function

???????? ???????????????????????????????? (LPVOID)i,????? // Data for thread func()

???????? ???????????????????????????????? 0,???????? ?????// Thread start mode

???????? ???????????????????????????????? NULL);????????? // Returned thread ID

???? }

???? WaitForMultipleObjects(gThreadCount, threadHandles,? TRUE, INFINITE);

???? DeleteCriticalSection(&gCS);

?

???? printf("%f\n", gSum / gIterations);

?

???? return 0;

}

?

Feedback

# re: 多線程計算PI碰到的問題  回復  更多評論   

2007-03-24 15:05 by 小熊
這應該算是由race condtion產生的問題吧?

# re: 多線程計算PI碰到的問題  回復  更多評論   

2007-03-26 21:14 by 小熊
上面對gSum += 4.0f / (1.0f + dx*dx);//cause problems here!
的分解有誤,正確應該由如下這些匯編代碼組成:

00401065 fmul qword ptr [dx]
00401068 fadd qword ptr [__real@3ff0000000000000 (403168h)]
0040106E fdivr qword ptr [__real@4010000000000000 (403160h)]
00401074 fadd qword ptr [gSum (4040A8h)]
0040107A fstp qword ptr [gSum (4040A8h)]

而gSum += i;則被翻譯成如下這些匯編代碼:

00401080 fild dword ptr [i]
00401083 fadd qword ptr [gSum (4040A8h)]
00401089 fstp qword ptr [gSum (4040A8h)]

# re: 多線程計算PI碰到的問題  回復  更多評論   

2007-03-30 15:27 by 小熊
printf("Hello Thread %d\n", num);
這一句被分解為以下匯編代碼

00401026 mov esi,esp
00401028 mov ecx,dword ptr [num]
0040102B push ecx
0040102C push offset MSVCR71D_NULL_THUNK_DATA+28h (4030CCh)
00401031 call dword ptr [__imp__printf (40309Ch)]
00401037 add esp,8
0040103A cmp esi,esp
0040103C call _RTC_CheckEsp (4011D0h)
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            久久福利资源站| 中国女人久久久| 久久这里只有| 久久久91精品国产| 在线日本高清免费不卡| 老巨人导航500精品| 久久久久国产一区二区三区四区| 尤物精品在线| 亚洲精品国产精品国自产观看浪潮| 欧美1区2区3区| 一区二区三区日韩在线观看| 亚洲先锋成人| 好吊妞**欧美| 91久久久在线| 国产精品夫妻自拍| 久久久最新网址| 欧美激情视频一区二区三区免费| 亚洲天堂av在线免费| 午夜精品久久久久久久99樱桃| 韩国视频理论视频久久| 亚洲黄色一区| 国产色产综合产在线视频| 牛牛精品成人免费视频| 欧美视频官网| 你懂的视频欧美| 国产精品大片wwwwww| 裸体一区二区三区| 国产精品成人免费精品自在线观看| 久久久精品性| 欧美午夜电影完整版| 老牛嫩草一区二区三区日本| 欧美日本免费| 美女在线一区二区| 国产精品jizz在线观看美国| 模特精品裸拍一区| 国产精品视频一区二区高潮| 亚洲国产精品久久91精品| 国产精品美女久久久久久免费| 免费成人美女女| 国产欧美一区二区三区久久| 亚洲人成高清| 在线观看av不卡| 亚洲免费一在线| 一区二区三区免费在线观看| 久久日韩精品| 久久久av毛片精品| 国产精品国产三级国产普通话三级| 欧美大片免费看| 国内成+人亚洲+欧美+综合在线| 日韩午夜电影| 99精品视频一区| 欧美成人免费视频| 欧美高清在线视频| 韩国女主播一区| 久久国产精品网站| 久久精品99| 国产欧美不卡| 午夜精品久久久久久久99水蜜桃| 亚洲男女自偷自拍图片另类| 欧美日本三区| 99成人在线| 亚洲一区二区三| 欧美日在线观看| 99亚洲视频| 亚洲天堂视频在线观看| 欧美日韩黄视频| 日韩午夜av电影| 亚洲免费小视频| 国产精品日韩久久久久| 在线天堂一区av电影| 亚洲免费影视| 国产亚洲欧美一级| 久久精品人人做人人综合 | 欧美精品一卡二卡| 亚洲高清影视| 一本久道综合久久精品| 欧美男人的天堂| 亚洲视屏一区| 欧美在线视频一区二区| 国产亚洲欧美一区在线观看| 久久精品亚洲热| 美女在线一区二区| 日韩视频在线免费| 欧美视频第二页| 性8sex亚洲区入口| 欧美69wwwcom| 一区二区三区高清在线观看| 国产精品久久久久久一区二区三区| 午夜在线成人av| 欧美国产日韩免费| 亚洲无限av看| 国产一区二区三区的电影 | 夜夜嗨av色一区二区不卡| 亚洲综合另类| 影音先锋久久| 欧美日韩亚洲综合在线| 欧美在线短视频| 亚洲二区在线观看| 午夜国产精品影院在线观看 | 国产精品丝袜xxxxxxx| 欧美综合激情网| 亚洲欧洲一区二区三区| 亚洲欧美成人| 亚洲激情国产| 国产精品私人影院| 欧美xart系列高清| 亚洲资源av| 亚洲国产精品第一区二区三区| 亚洲一区二区三区精品视频| 狠狠色狠狠色综合日日五| 欧美激情在线| 久久久人人人| 亚洲永久精品国产| 亚洲国产色一区| 久久久久久久久一区二区| 99热精品在线| 在线看日韩av| 国产日韩欧美不卡| 欧美日韩第一页| 久久免费精品视频| 欧美在线观看天堂一区二区三区| 亚洲精品久久在线| 欧美本精品男人aⅴ天堂| 性久久久久久久| 亚洲影院一区| 一区二区三区四区国产| 亚洲国产精品成人综合| 今天的高清视频免费播放成人| 国产精品免费区二区三区观看| 欧美风情在线观看| 美女成人午夜| 久久噜噜噜精品国产亚洲综合| 亚洲永久免费| 一区二区三区国产在线| 亚洲人体影院| 亚洲欧洲在线播放| 亚洲国产专区校园欧美| 亚洲成人自拍视频| 欧美电影专区| 亚洲电影视频在线| 欧美福利在线观看| 欧美高清视频免费观看| 欧美国产另类| 欧美激情综合| 亚洲高清在线播放| 91久久国产综合久久蜜月精品| 免费日韩精品中文字幕视频在线| 欧美在线高清| 久久在线视频在线| 久久综合99re88久久爱| 麻豆成人在线| 欧美激情国产日韩精品一区18| 欧美国产一区二区| 亚洲精品久久久久久久久久久久久| 亚洲国产精品久久久久婷婷老年 | 亚洲国产欧美日韩| 亚洲精品一二| 亚洲一区二区黄色| 欧美一二三区精品| 久热精品在线| 欧美日韩国产一区精品一区| 欧美日韩视频一区二区| 国产精品一区二区在线观看| 国模叶桐国产精品一区| 亚洲国产精品久久久久| 一区二区av在线| 欧美伊人久久久久久午夜久久久久| 久久成人国产精品| 欧美激情国产日韩| 一区二区三区四区在线| 久久国产精品亚洲va麻豆| 美女任你摸久久| 欧美三级在线视频| 好吊视频一区二区三区四区| 在线观看一区二区精品视频| 一二三四社区欧美黄| 久久精品亚洲精品国产欧美kt∨| 欧美成人国产一区二区| 一区二区三区.www| 久久九九精品| 国产精品福利在线| 亚洲电影免费观看高清| 亚洲宅男天堂在线观看无病毒| 久久9热精品视频| 亚洲国产一区二区在线| 亚洲欧美国产三级| 欧美精品九九99久久| 国产一区二区看久久| 亚洲午夜激情免费视频| 欧美成人在线免费视频| 午夜久久久久久| 欧美精品性视频| 黄色欧美成人| 亚洲欧美日韩国产综合精品二区| 欧美成人久久| 久久久久免费| 国产偷国产偷亚洲高清97cao| 一区二区欧美国产| 亚洲第一毛片| 久久亚洲综合|