Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
магПП2013 / lec14.pptx
Скачиваний:
30
Добавлен:
19.04.2015
Размер:
709 Кб
Скачать

void ProcessInitialization (double* &pMatrix, double* &pVector,

12double* &pResult, double* &pProcRows, double* &pProcResult, int &Size, int &RowNum)

{

int RestRows;// число строк, которые нужно распределить int i;

if (ProcRank == 0)

{

printf("\nEnter size of matrix A (> p): "); scanf("%d", &Size);

// можно добавить проверку и цикл do-while

}

// рассылка значения Size всем процессам MPI_Bcast(&Size, 1, MPI_INT, 0, MPI_COMM_WORLD);

// осталось распределить между процессами Size строк матрицы А

13RestRows = Size;

for (i=0; i<ProcRank; i++)

{ RestRows = RestRows-RestRows/(ProcNum-i);}

// число строк на процесс

RowNum = RestRows/(ProcNum-ProcRank); pVector = new double [Size];

pResult = new double [Size];

pProcRows = new double [RowNum*Size];//элементы строк А для процесса pProcResult = new double [RowNum];

if (ProcRank == 0)

{

pMatrix = new double [Size*Size]; // случайное заполнение А и b

RandomDataInitialization(pMatrix, pVector, Size);

}}

14void RandomDataInitialization(double* pMatrix, double* pVector, int

Size)

{

int i, j;

srand(unsigned(clock()));// инициализация датчика случайных чисел for (i=0; i<Size; i++)

{

pVector[i] = rand()/double(1000); for (j=0; j<Size; j++)

pMatrix[i*Size+j] = rand()/double(1000);

}

}

15

void DataDistribution(double* pMatrix, double* pProcRows, double* pVector,

int Size, int RowNum)

{

int *pSendNum;//число элементов, отправляемых процессу

int *pSendInd;//индекс первого отправляемого процессу элемента int RestRows=Size;

// рассылка вектора b всем процессам

MPI_Bcast(pVector, Size, MPI_DOUBLE, 0, MPI_COMM_WORLD);

//подготовка к распределению строк матрицы А по процессам pSendInd = new int [ProcNum];//номера по процессам pSendNum = new int [ProcNum];// количества по процессам

RowNum = Size/ProcNum;// повторно определение числа строк

// определение отсылаемых строк для каждого процесса pSendNum[0] = RowNum*Size;

pSendInd[0] = 0;

16for (int i=1; i<ProcNum; i++)

{

RestRows = RestRows - RowNum;

RowNum = RestRows/(ProcNum-i);// нужно если нет кратности pSendNum[i] = RowNum*Size; //число элементов

pSendInd[i] = pSendInd[i-1]+pSendNum[i-1];//номер через смещение

}

// функция для отправления процессам разного числа элементов

MPI_Scatterv(pMatrix , pSendNum, pSendInd, MPI_DOUBLE, pProcRows,

pSendNum[ProcRank], MPI_DOUBLE, 0, MPI_COMM_WORLD);

// освобождение памяти delete [] pSendNum; delete [] pSendInd;

}

17

Функция MPI_Scatterv

 

int MPI_Scatterv(void* sendbuf, int *sendcounts, int *displs,

 

MPI_Datatype sendtype, void* recvbuf, int recvcount,

 

MPI_Datatype recvtype, int root, MPI_Comm comm)

 

sendbuf -

адрес начала буфера посылки

 

(используется только в процессе-отправителе root);

 

sendcounts

-

целочисленный массив

 

(размер равен числу процессов в группе),

 

содержащий число элементов, посылаемых каждому процессу;

 

displs

-

целочисленный массив

 

(размер равен числу процессов в группе),

 

i-ое значение определяет смещение относительно

 

начала sendbuf для данных, посылаемых процессу i;

 

sendtype

-

тип посылаемых элементов;

 

recvbuf

-

адрес начала буфера приема;

 

recvcount

-

число получаемых элементов;

 

recvtype

 

-

тип получаемых элементов;

 

root

-

номер процесса-отправителя;

 

comm

-

коммуникатор.

18

// будет выполняться каждым процессом

void ParallelResultCalculation(double* pProcRows, double* pVector, double* pProcResult, int Size, int RowNum)

{

int i, j;

for (i=0; i<RowNum; i++)

{

pProcResult[i] = 0;

for (j=0; j<Size; j++)

pProcResult[i] += pProcRows[i*Size+j]*pVector[j];

}

}

// будет выполняться каждым процессом для сбора результата

19void ResultReplication(double* pProcResult, double* pResult, int

Size, int RowNum)

{

int i;

int *pReceiveNum; //число получаемых элементов

int *pReceiveInd; //индекс элемента в векторе-результате int RestRows=Size;//число нераспределенных элементов

// временные массивы

pReceiveNum = new int [ProcNum];//количества по процессам pReceiveInd = new int [ProcNum];// номера по процессам

// определение частей (блоков элементов) вектора-результата pReceiveInd[0] = 0;

pReceiveNum[0] = Size/ProcNum;

20for (i=1; i<ProcNum; i++)

{

RestRows = RestRows - pReceiveNum[i-1]; pReceiveNum[i] = RestRows/(ProcNum-i); pReceiveInd[i] = pReceiveInd[i-1]+pReceiveNum[i-1];

}

// функция для сбора данных(для результата) на всех процессах группы

MPI_Allgatherv(pProcResult, pReceiveNum[ProcRank], MPI_DOUBLE,

pResult, pReceiveNum, pReceiveInd, MPI_DOUBLE, MPI_COMM_WORLD);

// освобождение памяти

delete [] pReceiveNum;

delete [] pReceiveInd;

}

21

Функция MPI_Allgatherv

int MPI_Allgatherv(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,MPI_Datatype recvtype, MPI_Comm comm) sendbuf - адрес начала буфера посылки;

sendcount - число посылаемых элементов; sendtype - тип посылаемых элементов; recvbuf - адрес начала буфера приема;

recvcount - число получаемых элементов (от каждого процесса); recvtype - тип получаемых элементов;

comm - коммуникатор.

Получателями являются все процессы группы.

Данные, посланные процессом i из своего буфера sendbuf, помещаются в i-ю порцию буфера recvbuf каждого процесса.

После завершения операции содержимое буферов приема recvbuf у

всех процессов одинаково.

 

// проверка результатов

 

void TestDistribution(double* pMatrix, double* pVector, double* pProcRows,

22

int Size, int RowNum, double* pResult, double t1, double t2)

{

if (ProcRank == 0)

{

printf("\nInitial Matrix: \n");

PrintMatrix(pMatrix, Size, Size);//самостоятельно printf("\nInitial Vector: \n"); PrintVector(pVector, Size);//самостоятельно printf("\n\nResult Vector: \n");

PrintVector(pResult, Size);

PrintTime(t1,t2);//самостоятельно

}

MPI_Barrier(MPI_COMM_WORLD);// все ждут процесс 0

Соседние файлы в папке магПП2013