MPI中的一次性数据类型是正确的和/或可接受的设计吗?

问题描述

下面是使用数据类型的MPI原型程序。 该代码是此示例的简化版本:https://mpi.deino.net/mpi_functions/MPI_Type_vector.html。 与许多其他示例一样,MPI数据类型仅创建一次并提交一次,并多次使用。

我对其进行了修改,以便在函数f)内传递的MPI消息旁边创建并提交该类型。 考虑到f在每次调用中都创建并提交了类型,本示例将询问重复调用函数f是否正确。

我希望以某种方式提交用于“一次性使用”的类型是错误的。

但是,该程序运行正常,并且在重复调用多次时不占用更多内存。

通常可以创建一个类型,多次提交(并销毁)它吗?

我期望程序最终会失败,因为类型被反复提交,这将消耗越来越多的内存。 (也就是说,提交的数据类型将消耗资源。) 特别是因为MPI中没有“取消提交”功能。 还有另一种选择,就是MPI_Type_free足够聪明,也可以“取消提交”数据类型。 在许多地方,我读到MPI一旦提交便会“编译”数据类型,因此有可能在数据类型句柄中“就地”完成了该操作。

尽管有一段时间,我还是因为这是因为MPI系统检测到同一类型正在被提交并且该提交没有执行任何操作(即,在检查后忽略了该提交)。 但是,当我使用所有不同的参数创建类型时,仍然没有额外的内存消耗。

注意:我了解创建数据类型和提交不是免费的,并且存在运行时开销,但是在stride是运行时变量的情况下,这可以简化程序的设计因为您不需要全局变量或全局注册函数。 此外,如果类型的参数在运行时发生更改,则无法进行预注册。 问题是,当重复调用这些数据类型时,这些提交是否确实占用了内存;如果要根据使用情况而不是全局创建这些类型,则这种设计是否正确。 MPI手册中没有这方面的内容,只有示例发生一次注册并且多次使用该类型的例子。

#include "mpi.h"
#include<assert.h>
#include <stdio.h>

// can this be called unlimited number of times?
void f(int stride,int* buffer,int rank){
    MPI_Datatype type,type2;

    MPI_Type_contiguous(3,MPI_INT,&type2);
    MPI_Type_commit(&type2);
    MPI_Type_vector(3,stride,3,type2,&type);
    MPI_Type_commit(&type);

    if(rank == 0){
        for(int i=0; i<24; i++) buffer[i] = i;
        MPI_Send(buffer,1,type,123,MPI_COMM_WORLD);
    }

    MPI_Status status;
    if (rank == 1){
        for(int i=0; i<24; i++) buffer[i] = -1;
        MPI_Recv(buffer,MPI_COMM_WORLD,&status);
    }
    MPI_Type_free(&type);  // this is important and doesn't affect one committed
    MPI_Type_free(&type2);
}

int main(int argc,char *argv[]){
    int rank,size;
    int buffer[24];


    MPI_Init(&argc,&argv);
    MPI_Comm_size(MPI_COMM_WORLD,&size);
    assert(size == 2);

    MPI_Comm_rank(MPI_COMM_WORLD,&rank);

    // one time call is ok,is many calls correct too?
    // for(int n = 0; n != 100000000; ++n) f(3,buffer,rank);
    f(3,rank);

    MPI_Finalize();
    return 0;
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)