大连东软信息学院-多核多线程-实验一_第1页
大连东软信息学院-多核多线程-实验一_第2页
大连东软信息学院-多核多线程-实验一_第3页
大连东软信息学院-多核多线程-实验一_第4页
大连东软信息学院-多核多线程-实验一_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、大连东软信息学院-多核多线程-实验一项目一 :Windows*Threads多线程编程模块一:基础模块HelloHelloHelloHelloTliread Th"ild Thread Thread4编译执行, 简答与思考:输出结果:请按任意键继续.1写出修改后的HelloThreads的代码hello IhreadfThreadl 3Hello Throadtlhrv&A 8Hello Thread.*T2 Heilo Thread!hread 1 请按任意键处续. / HelloThreads.cpp :定?§ 义。?t空?制?台? § 应?| 用?程

2、一?序.一 的 i 九 一 ? 口 一 2 点 i ? ?e#include "stdafx.h"#include <windows.h> const int numThreads = 4;DWORD WINAPI helloFunc(LPVOID arg)int myNum=*(int *)arg);printf( "Hello Thread!Thread %d n" ,myNum); return 0;int main( int argc,_TCHAR* argv口)HANDLE hThreadnumThreads;int tNumnum

3、Threads;for ( int i = 0; i < numThreads; i+) tNumi=i;hThreadi=CreateThread(NULL, 0, helloFunc, &tNumi, 0, NULL );WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE); return 0;2项目总结。在主线程中循环调用CreateThread ()函 数生成四个子线程分别去执行helloFunc ()函数,并将线程的句柄保存在hThread数组中,CreateThread()的第四个参数给每个线程 传递参

4、数tNum获取该线程号,由helloFunc ()的参数接收并指向内容。由于主线程为每 个子线程传递了不同的参数,所以通过子线程 的执行结果可以判断出四个线程的执行顺序。 这个实验要我们初步认识了程序的并行化设 计思想,为以后的并行化程序设计打下了基 础。3模块二:临界区模块3编译执行,记录结果:calculation wasPi = The time .secondsof6编译执行,记录结果:Pi =- 15 -The time of calculationwas7,719600seconds7 加速比:1.90503951,并行效率:0.476259简答与思考:1如何进行并行化的?请写出并

5、行化的思路与 具体的代码。答:在程序中创建两个子线程,另主线程等待所 有的子线程执行结束后退出。代码:#include "stdafx.h"#include <windows.h>#include <time.h>static long num_steps=1000000000;const int gNumThreads=2;double step=0.0,pi=0.0,sum=0.0;CRITICAL_SECTION gCS;DWORD WINAPI threadFunction(LPVOID pArg)int myNum=*(int *)pArg

6、);double sum1=0.0,x;for ( int i=myNum; i< num_steps; i+=gNumThreads)x = (i+0.5)*step;sum1 = sum1 + 4.0/(1.0 + x*x);EnterCriticalSection(&gCS);sum+=sum1;LeaveCriticalSection(&gCS);return 0;int main( int argc,_TCHAR* argv口) clock_t start, stop;start = clock();HANDLE threadHandlesgNumThreads

7、;int tNumgNumThreads;InitializeCriticalSection(&gCS); step = 1.0/( double ) num_steps;for (int i=0;i<gNumThreads;+i)tNumi=i;threadHandlesi=CreateThread(NULL,0,threadFunction,&tNumi,0,NULL); WaitForMultipleObjects(gNumThreads,threadHandles,TRUE,INFINITE);DeleteCriticalSection(&gCS); |

8、pi = step * sum; stop = clock();printf( "Pi = %12.12fn",pi);printf( "The time of calculation was %f secondsn",( double )(stop - start)/1000.0);return 0;4在本模块中,哪些变量是需要保护的?为什 么?采取什么方法实现的?答:1)临界资源是需要保护的,也就是 sum变量,这里将对sum的更新操作定义为临界区 操作2)在多线程程序中,对于在子线程执行的代码中出现的被更新的全局变量要多加考虑, 因为具有这种特点的

9、变量,很有可能会引起数据冲突,如果处理不好会使程序产生功能性 错误3) EnterCriticalSection(&gCS);sum+=sum1;LeaveCriticalSection(&gCS);函数对临界区进行初始化,然后谓(月I EnterCriticalSection(&gCS);函数获取临界区的访问权,访问结束后调用LeaveCriticalSection(&gCS);函数释放临界区的访问权,在退出程序前需要调用DeleteCriticalSection(&gCS);函数注销临界区,释放临界区资源。3是否可以对该并行化方案进行进一步的优化?

10、如何优化?答:可以。更改创建线程的数目,分别计算出加速比和 效率,比较结果进行取舍。4项目总结。在使用临界区时,可以根据需要,在程序中 定义多个临界区对象,用来对不同的代码段进行 互斥访问,这样做的好处是可以增加程序的并行 度。总之,在设计多线程程序时,应该为每一个 需要互斥的共享资源定义一个临界区变量。模块三:事件模块3 编译执行)记录结果:Result isiesult is 0.69314218The time ofcalculation was10,y70000 secondsseconds4阅读代码,回答下面问题。(1)主线程共创建 5 个子线程。(2)各子线程调用的函数各是什么?D

11、WORD WINAPI threadProc(LPVOID par)DWORD WINAPI masterThreadProc(LPVOID par)(3)主线程等待 4个子线程的执行结束。6改进后的,编译执行,记录结果: Result isof calculation简答与思考:1 在 WINAPIThe timewassecondsthreadProc(LPVOID par)函数threadCount 的sums的访问没中为什么用临界区互斥了线程对 访问?为什么对于全局数据变量有互斥?WINAPI threadProc(LPVOIDpar)函数使用多线程执行的threadCount是记录线

12、程个数的,而它对于masterThreadProc ()函数要等待 所有线程(threadCount )做完对sums的计算, 然后再进行最后的四个线程结构的累加,它是这 两个函数的共享变量,对于它的操作必须原子 化,以保证每次只有一个线程对其自增,所以使用临界区互斥了每个线程对threadCount的访问,避免了数据冲突的发生。而对于数据变量sums每一个数组元素下标值 是每个子线程获得的参数,该参数标记了各个子 线程,sums数组分别对应每一个线程,从而使每 个子线程操作的变量分别保存在对应的数组元 素中,四个线程互不影响,所以并不需要互斥。2简述源代码中存在的问题,详述提出的改进方 案及

13、相关代码。源代码中为使“ master”子线程等待其余四个 子线程执行完毕,使用空循环保持“ master”子 线程的“等待”状态,这显然不是好的方法;改 进方案中使用了事件,事件用于线程间的执行顺 序以保证对共享资源操作的完整性,本程序中,“master”子线程是另外创建的,它需要另外四 个子线程的执行结果,所以需要等待以保证获得它们的结果后再进行操作,使用事件机制,程序 中定义四个未激发的人工重置事件,“ master” 子进程在执行时以wait方式等待事件被激发,由 于其余四个子线程在完成任务后将事件从未激 发设置为激发态,从而使“ master”子线程继续 执行余下操作#include

14、 "stdafx.h"#include <conio.h>#include <windows.h>#include <math.h>#include <time.h>#define NUMTHREADS 4#define SERIES_MEMBER_COUNT 100000HANDLE *threadHandles, masterThreadHandle,*eventHandles;CRITICAL_SECTION countCS;double *sums;double x = 1.0, res = 0.0;int threa

15、dCount = 0;double getMember( int n, double x)double numerator = 1;for ( int i=0; i<n; i+ ) numerator = numerator*x;if ( n % 2 = 0 )return ( - numerator / n );elsereturn numerator/n;DWORD WINAPI threadProc(LPVOID par)int threadindex = *( int *)par);sumsthreadIndex = 0;for (int i=threadIndex; i<

16、SERIES_MEMBER_COUNT;i+=NUMTHREADS)sumsthreadIndex += getMember(i+1, x);SetEvent(eventHandlesthreadIndex);/Signal Master thread that one more processing thread is done/EnterCriticalSection(&countCS);/threadCount+;/LeaveCriticalSection(&countCS);delete par;return 0;DWORD WINAPI masterThreadPro

17、c(LPVOID par)for ( int i=0; i<NUMTHREADS+ + ) ResumeThread(threadHandlesi); / Start computing threads/while (threadCount != NUMTHREADS) / busy wait until all threads are done with computation of partial sumsWaitForMultipleObjects(NUMTHREADS,eventHandles,TRUE,INFINITE);res = 0;for (int i=0; i<N

18、UMTHREADS; i+)res += sumsi;return 0;int main()clock_t start,stop;threadHandles = new HANDLENUMTHREADS + 1;eventHandles = newHANDLENUMTHREADS +1 ;/InitializeCriticalSection(&countCS);sums = new double NUMTHREADS;start=clock();for (int i=0; i<NUMTHREADS;i+)int * threadIdPtr = new int ;*threadId

19、Ptr = i;threadHandlesi = CreateThread(NULL, 0, threadProc, threadIdPtr,CREATE_SUSPENDED, NULL);eventHandlesi=CreateEvent(NULL,TRUE,FALSE,NULL);threadHandlesNUMTHREADS = CreateThread(NULL, 0, masterThreadProc, NULL, 0, NULL);,SERIES_MEMBER_COUNT);printf( "Count of ln(1 + x) Mercator's series

20、 members is %dn",(double )x);printf( "Argument value of x is %fn"WaitForMultipleObjects(NUMTHREADS+1,threadHandles,TRUE,INFINITE);stop=clock();for (int i=0; i<NUMTHREADS+1; i+ ) CloseHandle(threadHandlesi);delete threadHandles;delete eventHandles;/DeleteCriticalSection(&countCS

21、);delete sums;printf( "Result is %10.8fn", res);printf( "By function call ln(1 + %f) = %10.8fn",x, log(1+x);printf( "The time of calculation was %f secondsn" ,( double )(stop-start)/1000.0);printf( "Press any key .");getch();return 0;3是否可以对该并行化方案进行进一步的优化?如何优化?

22、线程在被创建时就执行,不再去唤醒, “master”只需等待事件被激发,效率就会有所 提高。4项目总结。模块四:信号量模块3这是串行代码实现,编译执行,记录结果Total Words =784719Total n Woi-ds: = 494314Total Odd= 490405i_Il_Jl_ I_LjJ1_I6编译执行并行版本,多次运行,记录结果: 第1次执行结果:Petal Uords =976922Petal Even Uords = -492827otal Odd Hords = 489100第2次执行结果:Total Uords =?73817Total Even Woi*ds =

23、 4731?3Total Odd IPopds = 485148第3次执行结果:Total Uat'ds =935649Total Euen Uords = 493005TotAl Odd Words = 488S3110修正后项目的输出结果为:tai Words =984719ratal £ven Weirds = 494314fotal Odd ords = 490405_I I_j L_*_ I_LjJ I_I简答与思考:1 Semaphores项目与SemaphoreT项目执行结 果不一致的原因是什么?在多线程中 fd 和 TotalWords ,TotalEvent

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

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

26、de <windows.h>#include <stdio.h>#include <time.h>FILE *fd;int TotalEvenWords = 0, TotalOddWords = 0, TotalWords = 0;HANDLE hSem1,hSem2;const int NUMTHREADS = 4;int GetNextLine(FILE *f, char *Line)if (fgets(Line, 132, f)=NULL) if (feof(f) return EOF; else return 1;int GetWordAndLett

27、erCount( char *Line)int Word_Count = 0,OddWords=0,EvenWords=0, Letter_Count = 0;for ( int i=0;i<132;i+) if (Linei!=' ' )&&(Linei!=0)&&(Linei!=''n' ) Letter_Count+;else if (Letter_Count!=0)if (Letter_Count % 2) OddWords+;Word_Count+;Letter_Count = 0; else EvenWords+;Word_Count+;Letter_Count = 0; if (Linei=0) break; return (Word_Count*10000+OddWords*100+EvenWords);DWORD WINAPI CountWords(LPVOID arg)BOOL bDone = FALSE ;char inLine132;int lCount=0;while (!bDone) WaitForSingleObject(hSem1,INFINITE); / 进? bDone = (GetNextLine(fd, inLine) =

温馨提示

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

评论

0/150

提交评论