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

Kisser Leon

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

多線程計算PI碰到的問題

Posted on 2007-03-23 23:42 kk 閱讀(1966) 評論(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>
            欧美韩日一区| 在线成人黄色| 在线视频精品一区| 午夜精品久久久久久| 国产一区二区中文| 欧美日韩精品欧美日韩精品一| 先锋影音国产一区| 亚洲看片网站| 久久蜜桃精品| av成人免费| 亚洲高清二区| 影音先锋久久久| 国产视频在线观看一区二区三区 | 国产精品区一区二区三| 欧美一区二区三区在线视频| 一区二区三区成人精品| 欧美不卡激情三级在线观看| 一本一本a久久| 欧美性事在线| 久久亚洲免费| 欧美一区二区精品| 亚洲欧美日韩在线播放| 中国成人亚色综合网站| 亚洲黄色影片| 日韩视频二区| 日韩一级黄色片| 亚洲片区在线| 亚洲国产日韩欧美在线99| 一区二区在线观看av| 国产亚洲人成网站在线观看| 国产亚洲在线| 国内外成人在线视频| 国产亚洲一级| 欧美激情四色| 欧美精品播放| 欧美黄色aa电影| 久久久欧美精品sm网站| 男男成人高潮片免费网站| 久久久久久久久岛国免费| 久久精品九九| 麻豆成人在线| 亚洲国产另类久久久精品极度| 欧美va天堂| 亚洲人成在线播放| 99在线精品视频| 亚洲一区二区三区视频播放| 亚洲一区二区少妇| 欧美综合国产精品久久丁香| 久久久久欧美精品| 久久夜色精品国产欧美乱极品 | 亚洲一区二区在线视频| 午夜精品久久久久久久久| 欧美专区在线播放| 欧美aaa级| 亚洲美女在线看| 亚洲欧美日韩精品久久久| 亚洲自拍高清| 久久精品国产第一区二区三区| 狂野欧美激情性xxxx| 欧美日韩国产成人在线观看| 欧美激情1区2区3区| 国产酒店精品激情| 亚洲人成在线播放| 欧美亚洲三区| 亚洲国内在线| 午夜精品久久久久| 欧美激情精品久久久久久| 国产精品美女黄网| 亚洲国产精品一区二区久 | 羞羞色国产精品| 日韩一级黄色片| 一区二区三区四区五区精品| 欧美在线视频播放| 欧美色中文字幕| 激情综合视频| 午夜综合激情| 亚洲毛片在线看| 另类激情亚洲| 国产一区二区三区在线观看网站| 亚洲国产精品www| 午夜亚洲伦理| 亚洲精品在线观看免费| 免费在线欧美视频| 国产亚洲福利一区| 伊甸园精品99久久久久久| a91a精品视频在线观看| 男同欧美伦乱| 久久黄色影院| 欧美成人精品高清在线播放| 国产精品久久久久一区二区| 亚洲精品乱码久久久久久| 久热爱精品视频线路一| 欧美一区二区三区在| 国产精品久久久久久av福利软件 | 国产精品成人一区二区艾草| 亚洲日本欧美在线| 免费成人在线观看视频| 久久九九99| 伊人久久噜噜噜躁狠狠躁| 久久se精品一区二区| 欧美高清视频在线观看| 亚洲国产一区二区三区在线播| 久久久欧美一区二区| 在线成人免费视频| 久久躁日日躁aaaaxxxx| 久久精品国产99精品国产亚洲性色| 国产精品欧美日韩久久| 亚洲欧美成人精品| 中文在线一区| 国产精品视频第一区| 亚洲欧美日韩国产另类专区| 亚洲一区www| 国产乱码精品一区二区三区忘忧草| 韩国成人精品a∨在线观看| 久久成人国产| 美女主播精品视频一二三四| 亚洲国产精品第一区二区| 欧美成人第一页| 男女av一区三区二区色多| 亚洲精品国产欧美| 亚洲伦理自拍| 亚洲激情偷拍| 国产精品女主播一区二区三区| 亚洲制服欧美中文字幕中文字幕| 一区二区三区免费看| 国产欧美 在线欧美| 久久福利一区| 免费日韩成人| 一区二区三区久久| 亚洲免费视频网站| 在线日韩av永久免费观看| 亚洲国产欧美一区| 久久精品99| 在线观看日韩国产| 亚洲精品国产精品久久清纯直播| 国产精品久久久久9999高清| 久久精品视频免费播放| 欧美激情视频免费观看| 久久精品人人做人人爽| 欧美成人午夜剧场免费观看| 一区二区高清在线观看| 久久国产精品黑丝| 一本在线高清不卡dvd| 午夜免费久久久久| 在线亚洲欧美专区二区| 久久久高清一区二区三区| 亚洲在线观看免费| 国产免费亚洲高清| 久久99伊人| 欧美顶级少妇做爰| 99re6这里只有精品视频在线观看| 欧美激情小视频| 99视频精品在线| 欧美在线啊v| 怡红院精品视频在线观看极品| 久久综合九色综合欧美狠狠| 亚洲激精日韩激精欧美精品| 99这里有精品| 国产女优一区| 久久亚洲电影| 一区二区三区日韩欧美| 久久国内精品视频| 亚洲精品视频中文字幕| 欧美午夜视频| 久久久久国产一区二区| 亚洲精品欧美一区二区三区| 午夜精品久久久久久| 亚洲第一黄色网| 国产精品久久久久一区| 久久久一二三| 一二三区精品福利视频| 另类欧美日韩国产在线| 亚洲一二区在线| 精品成人在线视频| 欧美日韩在线电影| 久久另类ts人妖一区二区| 一区二区日韩免费看| 麻豆成人av| 欧美亚洲在线| 一区电影在线观看| 极品av少妇一区二区| 欧美三日本三级少妇三2023| 久久久最新网址| 亚洲综合成人婷婷小说| 亚洲精品黄网在线观看| 久久天天躁狠狠躁夜夜爽蜜月 | 国产精品成人aaaaa网站| 玖玖国产精品视频| 欧美一区二区三区日韩| 在线日韩中文字幕| 蜜臀av一级做a爰片久久| 亚洲欧美国产77777| 亚洲美女在线一区| 欧美国产一区二区在线观看 | 亚洲激情电影在线| 久久人人97超碰人人澡爱香蕉| 亚洲午夜av| 夜夜嗨一区二区| 亚洲欧洲视频在线| 国产视频一区在线|