Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Метод АТПО лр.doc
Скачиваний:
3
Добавлен:
01.07.2025
Размер:
561 Кб
Скачать
☆

Хід роботи

Розглянемо програму паралельного обчислення скалярного добутку векторів:

#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;

}