大连东软信息学院-多核多线程-实验一

上传人:非****1 文档编号:50724088 上传时间:2022-01-22 格式:DOCX 页数:17 大小:73.50KB
收藏 版权申诉 举报 下载
大连东软信息学院-多核多线程-实验一_第1页
第1页 / 共17页
大连东软信息学院-多核多线程-实验一_第2页
第2页 / 共17页
大连东软信息学院-多核多线程-实验一_第3页
第3页 / 共17页
资源描述:

《大连东软信息学院-多核多线程-实验一》由会员分享,可在线阅读,更多相关《大连东软信息学院-多核多线程-实验一(17页珍藏版)》请在装配图网上搜索。

1、大连东软信息学院-多核多线程-实验一项目一:Windows*Threads多线程编程模块一:基础模块HelloHelloHelloHelloTliread Thild Thread Thread4编译执行, 简答与思考:输出结果:请按任意键继续.1写出修改后的HelloThreads的代码helloIhreadfThreadl3HelloThroadtlhrv&A8HelloThread.*T2HeiloThread!hread1请按任意键处续./HelloThreads.cpp:定?义。?t空?制?台?应?|用?程一?序.一的i九一?口一2点i?e#includestdafx.h#inclu

2、deconstintnumThreads=4;DWORDWINAPIhelloFunc(LPVOIDarg)intmyNum=*(int*)arg);printf(HelloThread!Thread%dn,myNum);return0;intmain(intargc,_TCHAR*argv口)HANDLEhThreadnumThreads;inttNumnumThreads;for(inti=0;inumThreads;i+)tNumi=i;hThreadi=CreateThread(NULL,0,helloFunc,&tNumi,0,NULL);WaitForMultipleObjects

3、(numThreads,hThread,TRUE,INFINITE);return0;2项目总结。在主线程中循环调用CreateThread()函数生成四个子线程分别去执行helloFunc()函数,并将线程的句柄保存在hThread数组中,CreateThread()的第四个参数给每个线程传递参数tNum获取该线程号,由helloFunc()的参数接收并指向内容。由于主线程为每个子线程传递了不同的参数,所以通过子线程的执行结果可以判断出四个线程的执行顺序。这个实验要我们初步认识了程序的并行化设计思想,为以后的并行化程序设计打下了基础。3模块二:临界区模块3编译执行,记录结果:calculat

4、ion wasPi = The time .secondsof6编译执行,记录结果:Pi =- 16 -Thetimeofcalculationwas7,719600seconds7 加速比:1.90503951,并行效率:0.476259简答与思考:1如何进行并行化的?请写出并行化的思路与具体的代码。答:在程序中创建两个子线程,另主线程等待所有的子线程执行结束后退出。代码:#includestdafx.h#include#includestaticlongnum_steps=1000000000;constintgNumThreads=2;doublestep=0.0,pi=0.0,sum=

5、0.0;CRITICAL_SECTIONgCS;DWORDWINAPIthreadFunction(LPVOIDpArg)intmyNum=*(int*)pArg);doublesum1=0.0,x;for(inti=myNum;inum_steps;i+=gNumThreads)x=(i+0.5)*step;sum1=sum1+4.0/(1.0+x*x);EnterCriticalSection(&gCS);sum+=sum1;LeaveCriticalSection(&gCS);return0;intmain(intargc,_TCHAR*argv口)clock_tstart,stop;s

6、tart=clock();HANDLEthreadHandlesgNumThreads;inttNumgNumThreads;InitializeCriticalSection(&gCS);step=1.0/(double)num_steps;for(inti=0;igNumThreads;+i)tNumi=i;threadHandlesi=CreateThread(NULL,0,threadFunction,&tNumi,0,NULL);WaitForMultipleObjects(gNumThreads,threadHandles,TRUE,INFINITE);DeleteCritical

7、Section(&gCS);|pi=step*sum;stop=clock();printf(Pi=%12.12fn,pi);printf(Thetimeofcalculationwas%fsecondsn,(double)(stop-start)/1000.0);return0;4在本模块中,哪些变量是需要保护的?为什么?采取什么方法实现的?答:1)临界资源是需要保护的,也就是sum变量,这里将对sum的更新操作定义为临界区操作2)在多线程程序中,对于在子线程执行的代码中出现的被更新的全局变量要多加考虑,因为具有这种特点的变量,很有可能会引起数据冲突,如果处理不好会使程序产生功能性错误3)E

8、nterCriticalSection(&gCS);sum+=sum1;LeaveCriticalSection(&gCS);函数对临界区进行初始化,然后谓(月IEnterCriticalSection(&gCS);函数获取临界区的访问权,访问结束后调用LeaveCriticalSection(&gCS);函数释放临界区的访问权,在退出程序前需要调用DeleteCriticalSection(&gCS);函数注销临界区,释放临界区资源。3是否可以对该并行化方案进行进一步的优化?如何优化?答:可以。更改创建线程的数目,分别计算出加速比和效率,比较结果进行取舍。4项目总结。在使用临界区时,可以根据

9、需要,在程序中定义多个临界区对象,用来对不同的代码段进行互斥访问,这样做的好处是可以增加程序的并行度。总之,在设计多线程程序时,应该为每一个需要互斥的共享资源定义一个临界区变量。模块三:事件模块3编译执行)记录结果:Resultisiesultis0.69314218Thetimeofcalculation was10,y70000 secondsseconds4阅读代码,回答下面问题。(1)主线程共创建5个子线程。(2)各子线程调用的函数各是什么?DWORDWINAPIthreadProc(LPVOIDpar)DWORDWINAPImasterThreadProc(LPVOIDpar)(3)

10、主线程等待4个子线程的执行结束。6改进后的,编译执行,记录结果:Resultisof calculation简答与思考:1 在 WINAPIThetimewassecondsthreadProc(LPVOIDpar)函数threadCount 的sums的访问没中为什么用临界区互斥了线程对访问?为什么对于全局数据变量有互斥?WINAPI threadProc(LPVOIDpar)函数使用多线程执行的threadCount是记录线程个数的,而它对于masterThreadProc()函数要等待所有线程(threadCount)做完对sums的计算,然后再进行最后的四个线程结构的累加,它是这两个函

11、数的共享变量,对于它的操作必须原子化,以保证每次只有一个线程对其自增,所以使用临界区互斥了每个线程对threadCount的访问,避免了数据冲突的发生。而对于数据变量sums每一个数组元素下标值是每个子线程获得的参数,该参数标记了各个子线程,sums数组分别对应每一个线程,从而使每个子线程操作的变量分别保存在对应的数组元素中,四个线程互不影响,所以并不需要互斥。2简述源代码中存在的问题,详述提出的改进方案及相关代码。源代码中为使“master”子线程等待其余四个子线程执行完毕,使用空循环保持“master”子线程的“等待”状态,这显然不是好的方法;改进方案中使用了事件,事件用于线程间的执行顺序

12、以保证对共享资源操作的完整性,本程序中,“master”子线程是另外创建的,它需要另外四个子线程的执行结果,所以需要等待以保证获得它们的结果后再进行操作,使用事件机制,程序中定义四个未激发的人工重置事件,“master”子进程在执行时以wait方式等待事件被激发,由于其余四个子线程在完成任务后将事件从未激发设置为激发态,从而使“master”子线程继续执行余下操作#includestdafx.h#include#include#include#include#defineNUMTHREADS4#defineSERIES_MEMBER_COUNT100000HANDLE*threadHandle

13、s,masterThreadHandle,*eventHandles;CRITICAL_SECTIONcountCS;double*sums;doublex=1.0,res=0.0;intthreadCount=0;doublegetMember(intn,doublex)doublenumerator=1;for(inti=0;in;i+)numerator=numerator*x;if(n%2=0)return(-numerator/n);elsereturnnumerator/n;DWORDWINAPIthreadProc(LPVOIDpar)intthreadindex=*(int*)

14、par);sumsthreadIndex=0;for(inti=threadIndex;iSERIES_MEMBER_COUNT;i+=NUMTHREADS)sumsthreadIndex+=getMember(i+1,x);SetEvent(eventHandlesthreadIndex);/SignalMasterthreadthatonemoreprocessingthreadisdone/EnterCriticalSection(&countCS);/threadCount+;/LeaveCriticalSection(&countCS);deletepar;return0;DWORD

15、WINAPImasterThreadProc(LPVOIDpar)for(inti=0;iNUMTHREADS+)ResumeThread(threadHandlesi);/Startcomputingthreads/while(threadCount!=NUMTHREADS)/busywaituntilallthreadsaredonewithcomputationofpartialsumsWaitForMultipleObjects(NUMTHREADS,eventHandles,TRUE,INFINITE);res=0;for(inti=0;iNUMTHREADS;i+)res+=sum

16、si;return0;intmain()clock_tstart,stop;threadHandles=newHANDLENUMTHREADS+1;eventHandles=newHANDLENUMTHREADS+1;/InitializeCriticalSection(&countCS);sums=newdoubleNUMTHREADS;start=clock();for(inti=0;iNUMTHREADS;i+)int*threadIdPtr=newint;*threadIdPtr=i;threadHandlesi=CreateThread(NULL,0,threadProc,threa

17、dIdPtr,CREATE_SUSPENDED,NULL);eventHandlesi=CreateEvent(NULL,TRUE,FALSE,NULL);threadHandlesNUMTHREADS=CreateThread(NULL,0,masterThreadProc,NULL,0,NULL);,SERIES_MEMBER_COUNT);printf(Countofln(1+x)Mercatorsseriesmembersis%dn,(double )x);printf(Argumentvalueofxis%fnWaitForMultipleObjects(NUMTHREADS+1,t

18、hreadHandles,TRUE,INFINITE);stop=clock();for(inti=0;iNUMTHREADS+1;i+)CloseHandle(threadHandlesi);deletethreadHandles;deleteeventHandles;/DeleteCriticalSection(&countCS);deletesums;printf(Resultis%10.8fn,res);printf(Byfunctioncallln(1+%f)=%10.8fn,x,log(1+x);printf(Thetimeofcalculationwas%fsecondsn,(d

19、ouble)(stop-start)/1000.0);printf(Pressanykey.);getch();return0;3是否可以对该并行化方案进行进一步的优化?如何优化?线程在被创建时就执行,不再去唤醒,“master”只需等待事件被激发,效率就会有所提高。4项目总结。模块四:信号量模块3这是串行代码实现,编译执行,记录结果TotalWords=784719TotalnWoi-ds:=494314TotalOdd=490405i_Il_Jl_I_LjJ1_I6编译执行并行版本,多次运行,记录结果:第1次执行结果:PetalUords=976922PetalEvenUords=-492

20、827otalOddHords=489100第2次执行结果:TotalUords=?73817TotalEvenWoi*ds=4731?3TotalOddIPopds=485148第3次执行结果:TotalUatds=935649TotalEuenUords=493005TotAlOddWords=488S3110修正后项目的输出结果为:taiWords=984719ratalvenWeirds=494314fotalOddords=490405_II_jL_*_I_LjJI_I简答与思考:1Semaphores项目与SemaphoreT项目执行结果不一致的原因是什么?在多线程中fd和Tota

21、lWords,TotalEventWords)TotalOddWords属于共享变量,在并发执行的过程中会造成数据冲突。fd对于每个线程是互斥的,是因为在文件指针往下一行改变时,不准许其它线程对该操作有影响,不然就会造成该问题的计数结果不正确的现象;而TotalWords,TotalEventWords,TotalOddWords这几个变量,是计算总的字符串个数,含有偶数数量字符的字符串的个数及含有奇数个字符的字符串的个数,毋庸置疑,它们也是共享资源,在对他们进行累加时,要注意数据冲突。2如何修改SemaphoreT项目源代码?写出修改思路和关键代码。可以采用临界区的方法去做,也可以采用信号量

22、。信号量也是一种内核对象,它可以对当前的资源计数,这是与临界区最大的不同,当资源数量大于0时,等待该信号量的线程就可以获得该资源得以继续执行。改进方案:在代码中应用两个信号量hSeml,hSem2,hSeml用于线程对文件指针fd的互斥,hSem2用于对全局变量TotalWords,TotalEventWords,TotalOddWords的互斥,对于每一个子线程,由于我们的思路是按行计算,然后累加的,对于偶数数量字符的字符串的个数以及含有奇数数量字符串的个数计算,要注意采取巧妙点的处理办法。#includestdafx.h#include#include#includeFILE*fd;int

23、TotalEvenWords=0,TotalOddWords=0,TotalWords=0;HANDLEhSem1,hSem2;constintNUMTHREADS=4;intGetNextLine(FILE*f,char*Line)if(fgets(Line,132,f)=NULL)if(feof(f)returnEOF;elsereturn1;intGetWordAndLetterCount(char*Line)intWord_Count=0,OddWords=0,EvenWords=0,Letter_Count=0;for(inti=0;i132;i+)if(Linei!=)&(Line

24、i!=0)&(Linei!=n)Letter_Count+;elseif(Letter_Count!=0)if(Letter_Count%2)OddWords+;Word_Count+;Letter_Count=0;elseEvenWords+;Word_Count+;Letter_Count=0;if(Linei=0)break;return(Word_Count*10000+OddWords*100+EvenWords);DWORDWINAPICountWords(LPVOIDarg)BOOLbDone=FALSE;charinLine132;intlCount=0;while(!bDon

25、e)WaitForSingleObject(hSem1,INFINITE);/进?bDone=(GetNextLine(fd,inLine)=EOF);ReleaseSemaphore(hSem1,1,NULL);/出?if(!bDone)lCount=GetWordAndLetterCount(inLine);WaitForSingleObject(hSem2,INFINITE);/进?TotalWords+=lCount/10000;TotalOddWords+=(lCount%10000)/100;TotalEvenWords+=lCount%100;ReleaseSemaphore(h

26、Sem2,1,NULL);/出?return0;intmain()HANDLEhThreadNUMTHREADS;hSem1=CreateSemaphore(NULL,1,1,NULL);hSem2=CreateSemaphore(NULL,1,1,NULL);fd=fopen(InFile1.txt,r);/Openfileforreadfor(inti=0;iNUMTHREADS;i+)hThreadi=CreateThread(NULL,0,CountWords,NULL,0,NULL);WaitForMultipleObjects(NUMTHREADS,hThread,TRUE,INFINITE);fclose(fd);printf(TotalWords=%8dnn,TotalWords);printf(TotalEvenWords=%7dnTotalOddWords=%7dn,TotalEvenWords,TotalOddWords);getchar();return0;3是否还有更优的修改方案?是如何修改的?无4项目总结。信号量这种内核对象,常被用于对于有限数据空间是访问控制、对一段代码的线程访问数量的控制、对有限资源的访问控制这几个方面。信号量这种给资源计数的思想在很多方面都会用到,但是使用起来也要谨慎,用不好说不定会给程序带来潜在的死锁隐患。

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!