c++boostmpiboost-mpi

boost::iprobe does not return correct count


In the code below, while probing, the correct number of arrivals is not obtained. The same functionality is also tested with standard MPI functions and correct answer is obtained. Why Boost version does not produce the correct result?

Boost version:

#include <iostream>
#include <boost/mpi.hpp>

using namespace boost;
using namespace boost::mpi;

int main()
{ 
    environment env;
    communicator world;

    if (world.rank() == 0)
    {
        int a[70];

        auto req = world.isend(0, 0, a);
        //req.wait(); // does not make any difference on the result.

        optional<status> stat;
        while (!stat)
        {
            stat = world.iprobe(0, 0);

            if (stat)
            {
                optional<int> count = (*stat).count<int>();

                if (count)
                {
                    std::cout << *count << std::endl; // output: 2, expected: 70.
                }
            }
        }
    }

    return 0;
}

Standard version:

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

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

    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    if (rank == 0)
    {
        int a[70];            

        MPI_Request req;
        MPI_Status stat;

        MPI_Isend(a, 70, MPI_INT, 0, 0, MPI_COMM_WORLD, &req);
        //MPI_Wait(&req, &stat);

        int flag;
        MPI_Iprobe(0, 0, MPI_COMM_WORLD, &flag, &stat);
        if (flag)
        {
            int count;
            MPI_Get_count(&stat, MPI_INT, &count);
            std::cout << count << std::endl; // output: 70.
        }
    }

    MPI_Finalize();

    return 0;
}

Edit: Using isend(dest, tag, values, n) instead of isend(dest, tag, values) gave the correct answer where n is the number of elements in the array.


Solution

  • Your Boost version does not actually send 70 int, but one single int [70]. For Boost, this type is not an MPI datatype, hence the correct (*stat).count<decltype(a)>(); returns an empty optional.

    Now the documentation is a bit misleading:

    The type T must have an associated data type, i.e., is_mpi_datatype<T> must derive mpl::true_. In cases where the type T does not match the transmitted type, this routine will return an empty optional<int>.

    I seems that instead in cases where T does not match the transmitted type, you will get either a bogus result or an empty optional<int>. If it is not a mpi datatype, you get an empty optional<int>.

    The reason why you get 2 specifically is that Boost.MPI sends two messages for each non-MPI datatype message. One containing the size of the serialized buffer and the actual message. Your probe maches the size-message, containing one size_t, which has the same size as 2 int.

    Unfortunately Boost.MPI is full of subtle issues and bugs of this kind relating to the different way messages are actually transferred.