【问题标题】:Not quite understanding MPI不太了解MPI
【发布时间】:2021-09-18 06:43:36
【问题描述】:

我正在尝试使用 MPI 制作一个程序,该程序将使用 MPI 找到 PI 的值。

目前我可以通过这种方式找到总和:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NUMSTEPS 1000000

int main() {
        int i;
        double x, pi, sum = 0.0;
        struct timespec start, end;

        clock_gettime(CLOCK_MONOTONIC, &start);
        double step = 1.0/(double) NUMSTEPS;
        x = 0.5 * step;

        for (i=0;i<= NUMSTEPS; i++){
                x+=step;
                sum += 4.0/(1.0+x*x);
        }
        pi = step * sum;
        clock_gettime(CLOCK_MONOTONIC, &end);
        u_int64_t diff = 1000000000L * (end.tv_sec - start.tv_sec) + end.tv_nsec - start.tv_nsec;

        printf("PI is %.20f\n",pi);
        printf("elapsed time = %llu nanoseconds\n", (long long unsigned int) diff);

        return 0;
}

但这不使用 MPI。

所以我尝试在 MPI 中创建自己的。我的逻辑是:

  1. 根据我拥有的处理器数量将 1000000 分成相等的部分
  2. 计算每个范围的值
  3. 将计算值发送回主服务器,然后除以处理器数量。我想保持主线程空闲而不做任何工作。类似于主从系统。

这是我目前拥有的。这似乎不起作用,并且发送/接收会给出有关接收和发送不兼容变量的错误。

#include <mpi.h>
#include <stdio.h>
#include <string.h>
#define NUMSTEPS 1000000


int main(int argc, char** argv) {
    int  comm_sz; //number of processes
    int  my_rank; //my process rank

    // Initialize the MPI environment
    MPI_Init(NULL, NULL);
    MPI_Comm_size(MPI_COMM_WORLD, &comm_sz);
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

    // Get the name of the processor
    char processor_name[MPI_MAX_PROCESSOR_NAME];
    int name_len;
    MPI_Get_processor_name(processor_name, &name_len);

    // Slaves
    if (my_rank != 0) {
        
    // Process math then send 
    
    int i;
        double x, pi, sum = 0.0;

        double step = 1.0/(double) NUMSTEPS;
        x = 0.5 * step;

    // Find the start and end for the number
    int processors = comm_sz - 1;
    
    int thread_multi = NUMSTEPS / processors;
        
    int start = my_rank * thread_multi;
        
    if((my_rank - 1) != 0){
        start += 1;
    }
    
    int end = start + thread_multi ;
    
        for (i=start; i <= end; i++){
                x+=step;
                sum += 4.0 / (1.0 + x * x);
        }
        pi = step * sum;
        
        
    MPI_Send(pi, 1.0, MPI_DOUBLE 1, 0, MPI_COMM_WORLD);
        
    // Master
    } else {
        // Things in here only get called once.
        double pi = 0.0;
        double total = 0.0;
            for (int q = 1; q < comm_sz; q++) {
                MPI_Recv(pi, 1, MPI_DOUBLE, q, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
                total += pi;
        pi = 0.0;
            }
        
        // Take the added totals and divide by amount of processors that processed, to get the average
        double finished = total / (comm_sz - 1);
        
        // Print sum here
        printf("Pi Is: %d", finished);
    }
    // Finalize the MPI environment.
    MPI_Finalize();
    
}


我目前已经花了大约 3 个小时来解决这个问题。没用过 MPI。任何帮助将不胜感激。

【问题讨论】:

  • 将您的论点与 MPI_Send open-mpi.org/doc/v4.1/man3/MPI_Send.3.php 的文档进行比较
  • 通信模式是MPI_Reduce()的教科书示例。此外,如果 master 公平地分配工作而不是等待,它会更简单、更有效。

标签: c linux multithreading thread-safety mpi


【解决方案1】:

尝试使用更多编译器警告进行编译并尝试修复它们,例如-Wall -Wextra 应该可以为您提供有关问题所在的绝佳线索。

根据MPI_Send documentation,第一个参数是指针,因此您似乎忽略了自动“转换为指针”错误。您在MPI_Recv() 通话中遇到了同样的问题。

您可以尝试在MPI_RecvMPI_Send 中将pi 作为&amp;pi 传递,并检查是否可以解决错误。

作为注释,您可以将虚拟变量声明为 pi 作为主循环内的局部变量以避免副作用:

for (int q = 1; q < comm_sz; q++) {
    double pi = 0;
    MPI_Recv(&pi, 1, MPI_DOUBLE, q, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    total += pi;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    相关资源
    最近更新 更多