MPI学习(一)

2023-12-13 08:24:36

最近在狂补mpi的相关知识,看到一些不错的文章,比如

cnblogs.com/zhangyazhou/p/13376294.html

MPI_Scatterv函数 - Message Passing Interface | Microsoft Learn

记MPI_Scatterv 和 MPI_Gatherv学习过程_我讨厌你_的博客-CSDN博客

18.2.313. MPI_Scatterv — Open MPI 5.0.x documentation (open-mpi.org)?

我是这样计划的所有的临济表都在0号进程创建,然后再传输到其他进程。

/// <summary>
///  从零号进程向其他进程发送邻接表
/// </summary>
/// <param name="global_adjacency">需要发送的邻接表</param>
/// <param name="out_degree">每行邻接表的长度</param>
void synchronous_adjacency(std::vector<std::vector<int>>& global_adjacency, std::vector<int>& out_degree);
void MPIManager::synchronous_adjacency(std::vector<std::vector<int>>& global_adjacency, std::vector<int>& out_degree)
{
    
    if (rank == 0)
    {
        for (int ii = 1; ii < num_processes; ii++)
        {
            MPI_Send(out_degree.data(), out_degree.size(), MPI_INT, ii, 0, MPI_COMM_WORLD);
            for (int jj = 0; jj < global_adjacency.size(); jj++)
            {
                MPI_Send(global_adjacency[jj].data(), out_degree[jj], MPI_INT, ii, 0, MPI_COMM_WORLD);
            }
        }
    }
    else
    {
        MPI_Recv(out_degree.data(), out_degree.size(), MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        for (int jj = 0; jj < global_adjacency.size(); jj++)
        {
            global_adjacency[jj].resize(out_degree[jj]);
            MPI_Recv(global_adjacency[jj].data(), out_degree[jj], MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        }
    }
}

?当然也可采用广播的方式

#include <iostream>
#include <vector>
#include <mpi.h>

int main() {
    MPI_Init(NULL, NULL);

    int rank, size;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    std::vector<std::vector<int>> adjacencyList;

    if (rank == 0) {
        // 邻接表的根进程数据
        adjacencyList = { {1, 2}, {0, 2, 3}, {0, 1}, {1} };
    }

    // 广播邻接表数据
    int listSize = adjacencyList.size();
    MPI_Bcast(&listSize, 1, MPI_INT, 0, MPI_COMM_WORLD);

    if (rank != 0) {
        // 在其他进程中分配接收缓冲区
        adjacencyList.resize(listSize);
    }

    for (int i = 0; i < listSize; i++) {
        int listSizeLocal = adjacencyList[i].size();
        MPI_Bcast(&listSizeLocal, 1, MPI_INT, 0, MPI_COMM_WORLD);

        if (rank != 0) {
            // 在其他进程中分配接收缓冲区
            adjacencyList[i].resize(listSizeLocal);
        }

        // 广播每个顶点的邻接关系
        MPI_Bcast(adjacencyList[i].data(), listSizeLocal, MPI_INT, 0, MPI_COMM_WORLD);
    }

    // 打印接收到的邻接表
    std::cout << "Process " << rank << ": ";
    for (const auto& list : adjacencyList) {
        std::cout << "[";
        for (const auto& neighbor : list) {
            std::cout << neighbor << " ";
        }
        std::cout << "] ";
    }
    std::cout << std::endl;

    MPI_Finalize();

    return 0;
}

我之前一直不太清楚c里面三种传参方式的区别,在代码的时候,弄出很多错误,

C语言函数参数传递的两种方式:值传递和引用传递(包括整型变量和字符串变量)_c语言引用传递-CSDN博客

还有就是返回指针和引用指针的区别

返回指针:

  1. 返回指针意味着函数返回一个指向某个对象的内存地址的指针。
  2. 返回指针可以允许函数返回空指针(nullptr),表示没有有效的对象提供。
  3. 返回指针可以用于指向单个对象或动态分配的数组。
  4. 返回指针需要注意内存管理的责任,确保返回的指针在函数结束后仍然有效,并及时释放相关的内存。

返回引用的指针:

  1. 返回引用的指针意味着函数返回一个指向某个对象引用的指针。
  2. 返回引用的指针可以用于操作原始对象,而无需进行解引用操作。
  3. 返回引用的指针要求被引用的对象在函数调用期间保持有效,否则会导致未定义行为。
  4. 返回引用的指针通常用于指向单个对象,而不是数组。

还有就是在写很多的类文件中,一定要注意不可以类之间的相互引用。另外就是如果你没有项目引用,但是依然报一个连接错误,请清理项目,然后重新生成即可。

文章来源:https://blog.csdn.net/qq_39591612/article/details/134829853
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。