您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 企业文化 > 哈工大_软件学院_《并行程序设计》课程实验报告之二
《并行程序设计》课程实验报告实验2:基于WindowsThread和OpenMP的多线程编程姓名***院系软件学院学号**********任课教师张伟哲指导教师苏统华实验地点软件学院五楼机房实验时间2015年4月8日实验课表现出勤、表现得分实验报告得分实验总分操作结果得分一、实验目的要求:需分析本次实验的基本目的,并综述你是如何实现这些目的的?一、1.熟练掌握C++语言;。2、掌握VisualStudio*.NET*集成开发环境的使用;3、掌握Windows32ThreadAPI开发多线程程序;4、掌握Windows32ThreadAPI中互斥机制的使用方式二、1.掌握OpenMP的基本功能、构成方式、句法;2、掌握OpenMP体系结构、特点与组成;3、掌握采用OpenMP进行多核架构下多线程编程的基本使用方法和调试方法。二、实验内容该部分填写在实验过程中,你都完成了哪些工作。一、1.定位到文件夹Win32Threads\HelloThreads\,用MicrosoftVisualstudio打开文件HelloThread.sln,编译并运行程序;2.对main.cpp中函数进行修改,要求输出线程创建顺序(例如:HelloThread0,HelloThread1,HelloThread2等等);注意:利用CreateThread()循环变量作为每个线程的执行顺序唯一标识3.编译并多次运行程序,记录线程执行顺序,分析线程程序执行顺序是否不可预见及其产生原因4.定位到文件夹Win32Threads\Pi\,用MicrosoftVisualstudio打开文件Pi.sln,编译并运行程序;5.对此串行代码使用Windows32ThreadAPI进行线程化,要求4线程实现,且每次迭代计算仅由一个线程完成6.使用CRITICAL_SECTION机制和Semaphors机制对多线程共享变量进行互斥操作,避免数据竞争。二、1、关闭病毒扫描和监控程序;2、采用MicrosoftVisualStudio工具打开实验程序文件:/Helloworlds/Helloworlds.c;3、编译,运行程序并记录实验结果;4、在源程序代码中的找到主程序体:printf(HelloWorld\n);for(i=0;i6;i++)printf(Iter:%d\n,i);;加上#pragmaompparallel{}段5、采用/Qopenmp重新编译程序(使用Intel编译器,通过Intel命令窗口进入)C:\icl/QopenmpHelloWorlds.c;6、设定Openmp线程数:C:\SetOMP_NUM_THREADS=2;7、重新运行程序,观测实验结果,并记录。实验二积分方法求PI值的并行处理化算法1、关闭病毒扫描和监控程序;2、采用MicrosoftVisualStudio工具打开实验程序文件:/pi/pi.sln;3、编译,运行程序并记录实验结果;4、在源程序代码中的找到主程序体中进行omp方式优化5、采用/Qopenmp重新编译程序;三、实验结果记录实验结果。2.1一、(1)直接编译运行:(2)打印数值(3)每次打印10个Hello,会发现明显的乱序执行现象(4)运行程序(5)使用下面的多线程代码进行计算#includewindows.h#includestdio.hCRITICAL_SECTIONcSection;constintnumThreads=4;staticlongnum_steps=100000;doublestep,pi;doublex,sum=0.0;DWORDWINAPIhelloFunc(LPVOIDpArg){ints=*(int*)pArg;step=1.0/(double)num_steps;for(inti=s;is+25000;i++){x=(i+0.5)*step;EnterCriticalSection(&cSection);sum=sum+4.0/(1.0+x*x);LeaveCriticalSection(&cSection);}return0;}voidmain(){InitializeCriticalSection(&cSection);HANDLEhThread[numThreads];inttNum[numThreads];for(inti=0;inumThreads;i++){tNum[i]=i*25000;hThread[i]=CreateThread(NULL,512,helloFunc,(void*)&tNum[i],0,NULL);}WaitForMultipleObjects(numThreads,hThread,TRUE,INFINITE);pi=step*sum;printf(Pi=%12.9f\n,pi);getchar();}得到结果:(6)使用mutex进行互斥DWORDWINAPICountWords(LPVOIDarg){BOOLbDone=FALSE;charinLine[132];while(!bDone){bDone=(GetNextLine(fd,inLine)==EOF);if(!bDone){WaitForSingleObject(hMutex,INFINITE);TotalWords+=GetWordAndLetterCount(inLine);ReleaseMutex(hMutex);}}return0;}二、(1)修改程序如下#pragmaompparallelprintf(HelloWorld\n);for(i=0;i6;i++)printf(Iter:%d\n,i);使用cl直接编译运行使用icl/Qopenmp编译,并设置SetOMP_NUM_THREADS=2,运行结果如下:(2)积分法求PI直接运行使用OpenMP优化#pragmaompparallelforprivate(x)reduction(+:sum)for(i=0;inum_steps;i++){x=(i+.5)*step;sum=sum+4.0/(1.+x*x);}结果如下:八线程:(3)1.直接运行:2.使用OMP优化vslNewStream(&stream,BRNG,(int)clock());#pragmaompparallelforprivate(r)reduction(+:dUnderCurve)for(j=0;jiter/BLOCK_SIZE;j++){vdRngUniform(METHOD,stream,BLOCK_SIZE*2,r,0.0,1.0);//Createrandomnumbersintoarrayr#pragmaompparallelforprivate(x,y)reduction(+:dUnderCurve)for(i=0;iBLOCK_SIZE;i++){x=r[i];//XCoordinatey=r[i+BLOCK_SIZE];//YCoordinateif(x*x+y*y=1.0){//isdistancefromOriginunderCurvedUnderCurve++;}}}3.八线程四、思考题思考题1:串行程序采用Windows32ThreadAPI进行线程化基本步骤?1、将需要线程化执行的代码块抽出来,改写成函数。2、使用CreateThread函数创建线程,并把上一步的得到的函数的函数名作为参数传入CreateThread中。3、注意线程直接的竞争现象,通过加锁等手段避免线程之间的竞争影响运行结果思考题2:Windows32ThreadAPI几种共享数据互斥机制可以采用,如何应用?Windows32ThreadAPI共享数据互斥机制总共有四种:事件(Event)、临界区(Criticalsection)、互斥量(Mutex)、信号量(Semaphore)。现分别叙述如下:1、事件(Event):是WIN32提供的最灵活的线程间同步方式。使用方法:用CreateEvent创建一个事件。对于需要手工设置的事件,在需要该事件或者事件发生时,采用SetEvent及ResetEvent来进行设置。2、临界区(Criticalsection):防止多个线程同时执行一个代码段。使用方法:1)需要设置临界区时,要先定义临界区对象,采用CRITICAL_SECTIONg_cs;2)使用前需初始化临界区,采用InitializeCriticalSection(&g_cs);函数3)需要进入临界区时,采用:EnterCriticalSection(&g_cs);函数,从而阻止其他的线程进入。4)离开临界区时,采用:LeaveCriticalSection(&g_cs);,从而让其他的线程可以进入该临界区。5)当该临界区不再有使用价值时,需销毁临界区,采用:DeleteCriticalSection(&g_cs);3、互斥量(Mutex):互斥量通常用于协调多个线程或进程的活动,控制对资源的“锁定”和“取消锁定”,从而控制对共享资源的访问。使用方法:1)首先,建立互斥体对象,得到句柄使用HANDLECreateMutex()函数;2)然后,在线程可能产生冲突的区域前调用WaitForSingleObject函数,将句柄传给函数,请求占用互斥对象:dwWaitResult=WaitForSingleObject(hMutex,5000L);3)共享资源访问结束,释放对互斥体对象的占用:ReleaseMutex(hMutex);4)最后使用CloseHandle函数删除互斥体对象。4、信号量(Semaphore):信号对象允许多个有限个数的线程同时访问共享资源。使用方法:1)当需要信号量时要先调用CreateSemaphore函数创建信号量2)在需要请求资源时,调用WaitForSingleObject函数或者WaitForMultipleObject函数等待信号量。3)资源使用完毕后,调用ReleaseSemaphore函数释放信号量思考题3:OpenMP的主要功能,基本构成体有哪些?主要功能:OpenMP提供了对并行算法的高层的抽象描述,程序员通过在源代码中加入专用的pragma来指明自己的意图,由此编译器可以自动将程序进行并行化,并在必要之处加入同步互斥以及通信。提供标准性、可移植性。基本构成体:OpenMp由三大部分组成,分别是:1、编译制导(CompilerDirective)2、运行库例程(RuntimeLibrary)3、环境变量(EnvironmentVariables)思考题4:试分析如何使用OpenMP实现多线程并行运算,提高系统运算效能,其引入环节应如何选取?1.找到循环这类大量密集计算的代码2.加入#pragma预编译指令,使用多线程对代码进行优化3.注意对某些线程私有的变量进行保护,避免得到不正确的结果五、实验心得体会指导教师评语:日期:
本文标题:哈工大_软件学院_《并行程序设计》课程实验报告之二
链接地址:https://www.777doc.com/doc-2581792 .html