实验一:Windows*Threads多线程编程模块一:基础练习
4 编译执行,输出结果:
简答与思考:
1写出修改后的HelloThreads的代码。
#include "stdafx.h"
#include
const int numThreads = 4;
DWORD WINAPI helloFunc(LPVOID pArg)
{
int myNum=*((int*)pArg);
printf("Hello Thread %d \n",myNum);
return 0;
}
int main()
{
HANDLE hThread[numThreads];
int tNum[10];
for (int i = 0; i < numThreads; i++)
{ tNum[i]=i;
hThread[i] =
CreateThread(NULL, 0, helloFunc, &tNum[i], 0, NULL );
}WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE);
return 0;
}
修改后结果
2实验总结
模块二:临界区实验
2编译执行,Pi的值为:
3编译执行,Pi的值为:
简答与思考:
1 如何进行并行化的?请写出并行化的思路与具体的代码。// WinPi.cpp : 定义控制台应用程序的入口点
//
#include "stdafx.h"
#include
#include
static long num_steps=1000000000;
double step, pi;
CRITICAL_SECTION gCS; //定义全局的临界变量gCS
const int numThreads = 2;
double dAllSum;
DWORD WINAPI PiCalculationThread(LPVOID p)
{
int j = *(int *)p;
double dSum = 0;
double dx;
int ii;
printf("This is the thread %d computing:\n",j);
for( ii = j ; ii < num_steps ; ii+=numThreads ){
dx = (ii+0.5)*step;
dSum = dSum + 4.0/(1.0 + dx*dx);
}
EnterCriticalSection(&gCS); //进入临界区
dAllSum += dSum;
LeaveCriticalSection(&gCS); //离开临界区
printf("The thread %d computation has finished:\n",j);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
clock_t start1;
clock_t stop1;
start1= clock(); //开始计时
HANDLE PiCalculation[numThreads];
int tmp[numThreads];
step = 1.0/(double) num_steps;
InitializeCriticalSection(&gCS);
for( int ia = 0 ; ia < numThreads ; ia++ ){
tmp[ia] = ia;
PiCalculation[ia] = CreateThread(NULL , 0 , PiCalculationThread , &tmp[ia] , 0 , NULL);
}
WaitForMultipleObjects (numThreads,PiCalculation,TRUE,INFINITE);
DeleteCriticalSection(&gCS);
pi = step * dAllSum;
printf("Pi = %12.9f\n",pi);
stop1 = clock(); //停止计时
printf("The time of calculation was %f seconds \n",(double)(stop1 - start1)/1000.0);
//输出运行时间
}
2 在本实验中,哪些变量是需要保护的?采取什么方法实现的?
dAllSum变量需要保护
EnterCriticalSection(&gCS); //进入临界区
dAllSum += dSum;
LeaveCriticalSection(&gCS); //离开临界区
printf("The thread %d computation has finished:\n",j);
3是否可以对该并行化方案进行进一步的优化?如何优化?
更改不同的线程数,计算加速比和效率,结果最好的那个线程数作为程序运行的最佳线程数4 实验总结
模块三:事件实验
3 编译执行,Result is
The time of calculation was 19.55700seconds 4阅读代码,回答下面问题。
(1)主线程共创建 2 个子线程。
(2)各子线程调用的函数各是什么?
Count threadProc
(3)主线程等待 2 个子线程的执行结束。
6 改进后的,编译执行,Result
is
The time of calculation was 15.122000 seconds
简答与思考:
1 在WINAPI threadProc(LPVOID par){}函数中为什么用临界区互斥了线程对threadCount的访问?为什么对于全局数据变量sums的访问没有互斥?
WINAPI threadProc(LPVOID par){}函数使用多线程执行的threadCount 对于WINAPI threadProc(LPVOID par){}函数是共享变量,如果不使用临界区互斥了线程对threadCount 的访问会造成数据冲突。
2 简述源代码中存在的问题,详述提出的改进方案及相关代码。
// ThreadEvent.cpp : 定义控制台应用程序的入口点
//
#include "stdafx.h"
#include
#include
#include
#include
#include
#define NUMTHREADS 4
#define SERIES_MEMBER_COUNT 100000
HANDLE *threadHandles, masterThreadHandle,*eventHandle;
CRITICAL_SECTION countCS;
double *sums;
double x = 1.0, res = 0.0;
int threadCount = 0;
double getMember(int n, double x)
{
double numerator = 1;
for( int i=0; i numerator = numerator*x; if ( n % 2 == 0 ) return ( - numerator / n ); else return numerator/n; } DWORD WINAPI threadProc(LPVOID par) { int threadIndex = *((int *)par); sums[threadIndex] = 0; for(int i=threadIndex; i sums[threadIndex] += getMember(i+1, x); SetEvent(eventHandle[threadIndex]); delete par; return 0; } DWORD WINAPI masterThreadProc(LPVOID par) { for( int i=0; i WaitForMultipleObjects(NUMTHREADS,eventHandle,TRUE,INFINITE); // busy wait until all threads are done with computation of partial sums res = 0; for(int i=0; i res += sums[i]; return 0; } int _tmain(int argc, _TCHAR* argv[]) { clock_t start, stop; threadHandles = new HANDLE[NUMTHREADS + 1]; eventHandle = new HANDLE[NUMTHREADS + 1]; sums = new double[NUMTHREADS]; start = clock(); for(int i=0; i { int * threadIdPtr = new int; *threadIdPtr = i; threadHandles[i] = CreateThread(NULL, 0, threadProc, threadIdPtr, CREATE_SUSPENDED, NULL); eventHandle[i] = CreateEvent(NULL,TRUE,FALSE,NULL); } threadHandles[NUMTHREADS] = CreateThread(NULL, 0, masterThreadProc, NULL, 0, NULL); printf("Count of ln(1 + x) Mercator's series members is %d\n",SERIES_MEMBER_COUNT); printf("Argument value of x is %f\n", (double)x); WaitForMultipleObjects(NUMTHREADS+1,threadHandles,TRUE,INFINITE); stop = clock(); for(int i=0; i delete threadHandles; delete eventHandle; delete sums; printf("Result is %10.8f\n", res); printf("By function call ln(1 + %f) = %10.8f\n",x, log(1+x)); printf("The time of calculation was %f seconds\n",((double)(stop - start)/1000.0)); printf("Press any key ... "); getch(); } 3是否可以对该并行化方案进行进一步的优化?如何优化? 应该优化优化*eventHandle; SetEvent(eventHandle[threadIndex]); eventHandle = new HANDLE[NUMTHREADS + 1]; 4 实验总结 模块四:信号量实验 3 确定串行版本项目为启动项,编译执行。 4 确定并行版本项目为启动项,编译执行。 修正后项目的输出结果为: 简答与思考: 1 Serial.cpp与Threaded.cpp代码执行结果不一致的原因是什么? 在多线程中fd 和TotalWords 为共享变量,在并发执行的过程中会造成数据冲突。 2 如何修改Threaded.cpp代码?写出修改思路和关键代码。 #include "stdafx.h" HANDLE semaphore1,semaphore2; FILE *fd; int TotalEvenWords = 0, TotalOddWords = 0, TotalWords = 0; 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 GetWordAndLetterCount(char *Line) { int Word_Count = 0, Letter_Count = 0; for (int i=0;i<132;i++) { if ((Line[i]!=' ')&&(Line[i]!=0)&&(Line[i]!='\n')) Letter_Count++; else { if(Letter_Count!=0){ if (Letter_Count % 2) { TotalOddWords++; Word_Count++; Letter_Count = 0; } else { TotalEvenWords++; Word_Count++; Letter_Count = 0; } } if (Line[i]==0) break; } } return (Word_Count); } DWORD WINAPI CountWords(LPVOID arg) { BOOL bDone = FALSE ; char inLine[132]; while (!bDone) { WaitForSingleObject(semaphore1,INFINITE); bDone = (GetNextLine(fd, inLine) == EOF); ReleaseSemaphore(semaphore1,1,NULL); if (!bDone){ WaitForSingleObject(semaphore2,INFINITE); TotalWords += GetWordAndLetterCount(inLine) ; ReleaseSemaphore(semaphore2,1,NULL); } } return 0; } int main() { HANDLE hThread[NUMTHREADS]; semaphore1 = CreateSemaphore(NULL,1,1,NULL); semaphore2 = CreateSemaphore(NULL,1,1,NULL); fd = fopen("InFile1.txt", "r"); for (int i = 0; i < NUMTHREADS; i++) hThread[i] = CreateThread(NULL,0,CountWords,NULL,0,NULL); WaitForMultipleObjects(NUMTHREADS, hThread, TRUE, INFINITE); fclose(fd); printf("Total Words = %8d\n\n", TotalWords); printf("Total Even Words = %7d\nTotal Odd Words = %7d\n", TotalEvenWords, TotalOddWords); } 3 是否还有更优的修改方案?为什么? 优化这些 HANDLE semaphore1,semaphore2; WaitForSingleObject(semaphore1,INFINITE); ReleaseSemaphore(semaphore1,1,NULL); WaitForSingleObject(semaphore2,INFINITE); ReleaseSemaphore(semaphore2,1,NULL); semaphore1 = CreateSemaphore(NULL,1,1,NULL); semaphore2 = CreateSemaphore(NULL,1,1,NULL); 在代码调优上做处理 4 实验总结