如何修复满足要求的 MPI 代码?

问题描述 投票:0回答:2

我有一个作业的书面代码,需要根据要求进行修复。你能帮帮我吗,我整个脑子都坏掉了。

作业: 根据变体使用阻塞和非阻塞操作编写程序:b = MIN(A+C) 提供多个进程中操作的执行。来源分布 数据应该使用非阻塞操作来执行,结果的收集应该使用阻塞操作。 结果 - 使用阻塞操作。

要求:

  1. 寻找最小值必须并行进行。
  2. 仅使用两点操作。
  3. 子数组检索阶段的辅助进程必须知道正在检索的数据的大小。
  4. 检查 if(rank==0) 应该在代码中出现一次(这已经被修复,但无论如何我都会保留它)。
  5. 不应将所有内容都计入 0 个进程(这一点非常重要)。

注释:

  • a - 标量
  • A - 维度为 N 的向量
  • MA - 维度为 NxN 的矩阵
  • a*B - 向量与标量的乘积
  • a*MB - 矩阵与标量的乘积
  • (A*B) - 向量 A 和 B 的标量积
  • (MA*MB) - 矩阵 MA 和 MB 的乘积
  • (MA*B) - 矩阵与向量的乘积
  • SORT(A) - 按升序对向量 A 进行排序
  • MIN(A) - 搜索向量的最小元素
  • MAX(A) - 搜索向量的最大元素
  • TRANS(MA) - 转置矩阵 MA
  • MAX(MA) - 搜索矩阵的最大元素
  • MIN(MA) - 搜索矩阵的最小元素
  • SORT(MA) - 按降序对矩阵行进行排序

代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <mpi.h>
int main(int argc, char* argv[])
{
const int N = 30;
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);

int local_size = N / size;

srand(time(0) + rank);
int* A = new int[local_size];
int* C = new int[local_size];
for (int i = 0; i < local_size; i++)
{
    A[i] = rand() % 100;
    C[i] = rand() % 100;
}

printf("Process Rank: %d\n", rank);
printf("Vector A:");
for (int i = 0; i < local_size; i++)
{
    printf(" %d", A[i]);
}
printf("\n");

printf("Vector C:");
for (int i = 0; i < local_size; i++)
{
    printf(" %d", C[i]);
}
printf("\n");

int local_min_A = A[0];
int local_min_C = C[0]; 
for (int i = 0; i < local_size; i++)
{
    if (A[i] < local_min_A)
    {
        local_min_A = A[i];
    }
    if (C[i] < local_min_C)
    {
        local_min_C = C[i];
    }
}

int local_min_sum = local_min_A + local_min_C;

printf("Local b min(A + C) = %d + %d = %d\n", local_min_A, local_min_C, local_min_sum);

if (rank == 0)
{
    int global_min_A = local_min_A;
    int global_min_C = local_min_C;
    int global_min_sum = local_min_sum;

    for (int i = 1; i < size; i++)
    {
        int recv_min_A, recv_min_C, recv_min_sum, recv_local_size;
        MPI_Recv(&recv_min_A, 1, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        MPI_Recv(&recv_min_C, 1, MPI_INT, i, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        MPI_Recv(&recv_min_sum, 1, MPI_INT, i, 2, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

        if (recv_min_A < global_min_A)
        {
            global_min_A = recv_min_A;
        }
        if (recv_min_C < global_min_C)
        {
            global_min_C = recv_min_C;
        }
        if (recv_min_sum < global_min_sum)
        {
            global_min_sum = recv_min_sum;
        }
    }

    printf("Global b min(A + C) = %d\n", global_min_sum);
}
else
{
    MPI_Send(&local_min_A, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
    MPI_Send(&local_min_C, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
    MPI_Send(&local_min_sum, 1, MPI_INT, 0, 2, MPI_COMM_WORLD);
}

delete[] A;
delete[] C;

MPI_Finalize();
return 0;
}

总和计算示例

#include <iostream>
#include <time.h>
#include <mpi.h>
using namespace std;
#define n 40000000L
int main(int argc, char** argv){
int rank,size;
MPI_Status st;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
if (!rank){
double *x, sum=0, d;
x=new double[n];
srand((unsigned)time(0));
for (int i=0; i<n; i++)
x[i]=(rand()%20)/2.;
unsigned pSize = n/(size-1);
printf("Master started!\n");
for (int i=1; i<size; i++) {
MPI_Send(&pSize,1,MPI_UNSIGNED,i,0,MPI_COMM_WORLD);
MPI_Send(x+(i-1)*pSize,pSize,MPI_DOUBLE,i,0,MPI_COMM_WORLD);
cout << "Master sent " << 
pSize << endl;
}
for (int i=pSize*(size-1); i<n; i++)
sum+=x[i];
for (int i=1; i<size; i++) {
MPI_Recv(&d, 1, MPI_DOUBLE, i,MPI_ANY_TAG, MPI_COMM_WORLD, &st);
cout << "Got sum from " << i<< ": sum="<< d << endl;
sum+=d;
}
cout << "Sum=" << sum << endl;
MPI_Finalize();
delete[] x;
return 0;
} else {
double *data, s = 0;
unsigned count;
data=new double[count];
MPI_Recv(&count, 1, MPI_UNSIGNED, 0,MPI_ANY_TAG, MPI_COMM_WORLD, &st);
MPI_Recv(data, count, MPI_DOUBLE, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &st);
cout << "Rank " << rank << " got " << count << endl;
for (unsigned i=0; i<count; i++)
s+=data[i];
MPI_Send(&s,1,MPI_DOUBLE,0,0,MPI_COMM_WORLD);
MPI_Finalize();
delete[] data;
return 0;
}
}
c mpi
2个回答
0
投票

…b = MIN(A+C)…

int local_min_A = A[0];
int local_min_C = C[0]; 
for (int i = 0; i < local_size; i++)
{
   if (A[i] < local_min_A)
   {
       local_min_A = A[i];
   }
   if (C[i] < local_min_C)
   {
       local_min_C = C[i];
   }
}

int local_min_sum = local_min_A + local_min_C;

您计算的是 MIN(A)+MIN(C),而不是 MIN(A+C)


0
投票

我重新编写了代码,但是导师说我错误地使用了阻塞和非阻塞操作。

源数据的分发应使用非阻塞操作来执行,结果的收集应使用阻塞操作来执行。结果 - 使用阻塞操作。

#define N 20
    
    void PrintVector(double V[N])
    {
        for (int i = 0; i < N; i++)
        {
            printf("%.2f ", V[i]);
        }
        printf("\n");
    }
    
    int main(int argc, char* argv[])
    {
        MPI_Init(&argc, &argv);
        MPI_Status st;
        int rank, size;
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
        MPI_Comm_size(MPI_COMM_WORLD, &size);
        double* A, * C;
    
        A = new double[N];
        C = new double[N];
        double localMin = DBL_MAX;
        MPI_Request request;
    
        if (!rank)
        {
            srand((unsigned)time(0));
            for (int i = 0; i < N; i++) {
                A[i] = (rand() % 20) / 2.;
                C[i] = (rand() % 20) / 2.;
            }
    
            unsigned pSize = N / (size - 1);
            printf("Master started!\n");
            for (int i = 1; i < size; i++)
            {
                MPI_Isend(&pSize, 1, MPI_UNSIGNED, i, 0, MPI_COMM_WORLD, &request);
                MPI_Isend(A + (i - 1) * pSize, pSize, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &request);
                MPI_Isend(C + (i - 1) * pSize, pSize, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &request);
                cout << "Master sent " << pSize << endl;
            }
    
            printf("Vector A:");
            PrintVector(A);
            printf("Vector C:");
            PrintVector(C);
    
            for (int i = (size - 1) * pSize; i < N; i++) {
                double temp = A[i] + C[i];
                localMin = min(localMin, temp);
            }
    
            for (int i = 1; i < size; i++)
            {
                double receivedMin;
                MPI_Recv(&receivedMin, 1, MPI_DOUBLE, i, MPI_ANY_TAG, MPI_COMM_WORLD, &st);
                localMin = min(localMin, receivedMin);
            }
            printf("\nMinumum b = min(A+C) = %f", localMin);
        }
        else {
            double* dataA, * dataC;
            unsigned count;
            MPI_Recv(&count, 1, MPI_UNSIGNED, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &st);
            dataA = new double[count];
            dataC = new double[count];
            MPI_Recv(dataA, count, MPI_DOUBLE, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &st);
            MPI_Recv(dataC, count, MPI_DOUBLE, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &st);
            cout << "Rank " << rank << " got " << count << endl;
            for (unsigned i = 0; i < count; i++)
            {
                double temp = dataA[i] + dataC[i];
                localMin = min(localMin, temp);
            }
    
            MPI_Send(&localMin, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
    
            delete[] dataA;
            delete[] dataC;
        }
        delete[] A;
        delete[] C;
        MPI_Finalize();
    }
© www.soinside.com 2019 - 2024. All rights reserved.