MPI_Pack:无效缓冲区指针

MPI_Pack: Invalid buffer pointer

本文关键字:缓冲区 指针 无效 Pack MPI      更新时间:2023-10-16

所以,这就是我的任务。我应该在主进程中读取K - 1个三元组(K -是进程数)。该三元组由两个整型数和一个双精度数组成。我必须使用MPI_Pack和一个集体操作来将这个三元组发送给其他进程。但是当使用MPI_Pack时,我得到一个错误:无效缓冲区指针。下面是我的代码:

int flag;
    MPI_Initialized(&flag);
    if (flag == 0)
        return;
    int rank, size;
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    int* intbuf = new int[2];
    double doublebuf;
    byte* rbuf = new byte[(size - 1)*(2 * sizeof(int)+sizeof(double))];
    if (rank == 0) {
        int pos = 0;
        for (int i = 0; i < size - 1; ++i){
            pt >> intbuf[1] >> intbuf[2] >> doublebuf; //pt is from the special library and it's okay
            MPI_Pack(intbuf, 2, MPI_INT, rbuf, sizeof(int)* 2, &pos, MPI_COMM_WORLD);
            MPI_Pack(&doublebuf, 1, MPI_DOUBLE, rbuf, sizeof(double), &pos, MPI_COMM_WORLD);
        }
    }
    MPI_Bcast(rbuf, sizeof(rbuf), MPI_PACKED, 0, MPI_COMM_WORLD);
    if (rank != 0){
        int pos = 0;
        for (int i = 0; i < size - 1; ++i){
            MPI_Unpack(rbuf, sizeof(int)* 2, &pos, intbuf, 2, MPI_INT, MPI_COMM_WORLD);
            MPI_Unpack(rbuf, sizeof(double), &pos, &doublebuf, 1, MPI_DOUBLE, MPI_COMM_WORLD);
            pt << intbuf[1] << intbuf[2] << doublebuf;
        }
    }

我做错了什么?

主要问题来自这一行:

MPI_Bcast(rbuf, sizeof(rbuf), MPI_PACKED, 0, MPI_COMM_WORLD);

更具体地说,它来自sizeof(rdbuf),应该被pos取代。事实上,sizeof(rdbuf)是一个sizeof(byte*),这取决于你的操作系统可能是4或8,但这将与你试图传输的数据大小无关……如果这个问题解决了,你的代码可能会"工作"。

然而,这仍然有很多问题:

  1. 你用某种任意大小分配你的打包缓冲区,这几乎没有意义。通常,要知道打包一些数据需要多少内存,应该使用MPI_Pack_size()
  2. 你为什么要使用MPI_Pack()呢?这个函数是PVM遗留下来的。并行虚拟机),这是一个消息传递库预先存在的MPI。此函数的目的是简化从PVM到MPI的转换,但肯定不能用于从头开发。

为了解决你的问题,我建议你调用2个不同的MPI_Bcast(),一个是你的2个整数,一个是你的双精度。这是非常简单直接的。

另一种可能性(如果可伸缩性很重要的话更好)是创建一个包含int型和double型的结构体,并使用MPI_Type_create_struct()创建一个匹配的MPI结构化类型。

所以我刚刚修正了我的错误。错误是在打包数据时发生的:MPI_Pack的第5个协议并不意味着你打包了多少数据,它意味着你的缓冲区的大小(在我的情况下,缓冲区是rbuf), MPI_Unpack的第二个参数具有相同的语义。这是固定的代码。它的工作原理。

int* intbuf = new int[2];
    double doublebuf;
    int N = (size - 1)*(2 * sizeof(int)+sizeof(double));
    byte* rbuf = new byte[N];
    int pos = 0;
    if (rank == 0) {
        for (int i = 0; i < size - 1; ++i){
            pt >> intbuf[0] >> intbuf[1] >> doublebuf;
            MPI_Pack(intbuf, 2, MPI_INT, rbuf, N, &pos, MPI_COMM_WORLD);
            MPI_Pack(&doublebuf, 1, MPI_DOUBLE, rbuf, N, &pos, MPI_COMM_WORLD);
        }
    }
    MPI_Bcast(rbuf, N, MPI_PACKED, 0, MPI_COMM_WORLD);
    if (rank != 0){
        int pos = 0;
        for (int i = 0; i < size - 1; ++i){
            int* intbuf_out = new int[2];
            double doublebuf_out;
            MPI_Unpack(rbuf, N, &pos, intbuf_out, 2, MPI_INT, MPI_COMM_WORLD);
            MPI_Unpack(rbuf, N, &pos, &doublebuf_out, 1, MPI_DOUBLE, MPI_COMM_WORLD);
            pt << intbuf_out[0] << intbuf_out[1] << doublebuf_out;
            delete(intbuf_out);
        }
    }