- •Хід роботи
- •Включення і настройка mpi відладника в ms vs
- •Програма 'π': паралельне інтегрування по формулі трапецій
- •Основні поняття mpi
- •Хід роботи
- •Завдання
- •Варіанти завдань
- •Хід роботи
- •Контрольні питання
- •Лабораторна робота № 4 Тема. Організація паралельного множення матриць
- •Короткі теоретичні відомості
- •Завдання
- •Хід роботи
- •Завдання
- •Контрольні запитання
- •Список літератури
Хід роботи
Розглянемо програму паралельного обчислення скалярного добутку векторів:
#include "stdafx.h"
#include <process.h>
struct Interval
{
HANDLE hThread;
HANDLE evStart;
unsigned First;
unsigned To;
float Result;
float *Vector1;
float *Vector2;
Interval() :
First(0), To(0), Vector1(NULL), Vector2(NULL),
Result(0.0f),
hThread(NULL), evStart(NULL) {}
};
unsigned __stdcall ThreadFunction(void *pData);
float DotProduct(float *Vector1, float *Vector2,
unsigned VectorSize);
unsigned GetNumberOfProcessors();
int main(int argc, char *argv[])
{
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
const unsigned VectorSize = 13;
float *Vector1 = new float[VectorSize];
float *Vector2 = new float[VectorSize];
printf("Dot product %f\n",
DotProduct(Vector1, Vector2, VectorSize));
delete[] Vector2;
delete[] Vector1;
return 0;
}
float DotProduct(float *Vector1, float *Vector2,
unsigned VectorSize)
{
if (!Vector1 || !Vector2)
return 0.0f;
unsigned ProcessorCount = GetNumberOfProcessors();
unsigned IntervalLength = VectorSize / ProcessorCount;
unsigned Remainder = VectorSize % ProcessorCount;
unsigned ProcessorsUsed =
(IntervalLength ? ProcessorCount : Remainder);
HANDLE *Handles = new HANDLE[ProcessorsUsed];
if (!Handles)
return 0.0f;
Interval *Intervals = new Interval[ProcessorsUsed];
if (!Intervals)
{
delete Handles;
return 0.0f;
}
// Nonsignaled manual-reset event
HANDLE evStart = CreateEvent(NULL, TRUE, FALSE, NULL);
unsigned From = 0;
unsigned i;
for (i = 0; i < ProcessorCount; i++)
{
unsigned To = From + IntervalLength;
if (Remainder)
To++, Remainder--;
if (To == From)
continue;
unsigned tid;
Intervals[i].First = From;
Intervals[i].To = To;
Intervals[i].evStart = evStart;
Intervals[i].hThread = (HANDLE)
_beginthreadex(NULL, 0, ThreadFunction,
&Intervals[i], 0, &tid);
From = To;
}
for (i = 0; i < ProcessorsUsed; i++)
{
Intervals[i].Vector1 = Vector1;
Intervals[i].Vector2 = Vector2;
Handles[i] = Intervals[i].hThread;
}
SetEvent(evStart);
WaitForMultipleObjects(ProcessorsUsed, Handles, TRUE,
INFINITE);
float Result = 0.0f;
for (i = 0; i < ProcessorsUsed; i++)
{
Result += Intervals[i].Result;
CloseHandle(Intervals[i].hThread);
}
CloseHandle(evStart);
delete[] Intervals;
delete[] Handles;
return Result;
}
unsigned __stdcall ThreadFunction(void *pData)
{
if (pData)
{
Interval &iv = *(Interval *)pData;
WaitForSingleObject(iv.evStart, INFINITE);
for (unsigned i = iv.First; i < iv.To; i++)
iv.Result += iv.Vector1[i] * iv.Vector2[i];
}
return 0;
}
unsigned GetNumberOfProcessors()
{
DWORD dwProcessAffinityMask, dwSystemAffinityMask;
unsigned n = 0;
if (GetProcessAffinityMask(GetCurrentProcess(),
&dwProcessAffinityMask,
&dwSystemAffinityMask))
{
for (DWORD dwMask = 0x00000001; dwMask;
dwMask <<= 1)
if (dwMask & dwProcessAffinityMask)
n++;
}
else
n = 1;
return n;
}
