显示MPI类型映射

显示MPI类型映射,mpi,typemaps,Mpi,Typemaps,在MPI中,类型映射是一个重要但混淆的概念。我想一个例行程序来显示或打印一个类型的地图为我 例如(取自MPI-3标准) 在类型图中显示结果 {(lb_marker, -3), (int, 0), (ub_marker, 6)}. 再次使用该类型: MPI_TYPE_CONTIGUOUS(2, type1, type2) 类型图是 {(lb_marker, -3), (int, 0), (int,9), (ub_marker, 15)} 我想要一种自动显示该类型映射的方法 当然,可以使用M

在MPI中,
类型映射是一个重要但混淆的概念。我想一个例行程序来显示或打印一个类型的地图为我

例如(取自MPI-3标准)

在类型图中显示结果

{(lb_marker, -3), (int, 0), (ub_marker, 6)}.
再次使用该类型:

MPI_TYPE_CONTIGUOUS(2, type1, type2) 
类型图是

{(lb_marker, -3), (int, 0), (int,9), (ub_marker, 15)}
我想要一种自动显示该类型映射的方法

当然,可以使用
MPI\u Type\u get\u contents
MPI\u Type\u get\u信封
并递归下降,直到命中内置类型。这是一个巨大的痛苦,我本以为20年后会有一些工具为我做这件事

有些工具很有前途,但不太管用:

  • 我找到了~2001年的地图。首先,它需要为现代Tcl/TK进行更新,修补以解决一些内存错误,然后再进行更新;您会得到一个无响应的GUI。相反,我正在寻找一个可以在运行时调用的库/例程

  • MPIDU_数据类型_deubg
    是一个特定于MPICH的内部类型转储例程。它不显示类型映射(它显示dataloop表示,再次关闭)

  • 曾经有一个名为XMPI的调试器,它在其功能中列出了显示MPI类型映射的能力。此调试器似乎是特定于LAM-MPI的,并且不使用get_内容/get_信封

如前所述,没有现成的好解决方案。在提供的链接的帮助下,我在上创建了此函数。我以您的示例为例进行了连续+调整大小测试(),输出为

contiguous + resize
"(LB, -3), (MPI_INT, 0), (MPI_INT, 9), (UB, 15)"
使用此函数,您只需执行
printMapDatatype(mydatatype)
。我希望这就是你一直在寻找的

以下是函数,以防:

MPI_Aint printdatatype( MPI_Datatype datatype, MPI_Aint prevExtentTot ) { 
    int *array_of_ints; 
    MPI_Aint *array_of_adds; 
    MPI_Datatype *array_of_dtypes; 
    int num_ints, num_adds, num_dtypes, combiner; 
    int i, j; 


    MPI_Type_get_envelope( datatype, &num_ints, &num_adds, &num_dtypes, &combiner ); 

    array_of_ints = (int *) malloc( num_ints * sizeof(int) ); 
    array_of_adds = (MPI_Aint *) malloc( num_adds * sizeof(MPI_Aint) ); 
    array_of_dtypes = (MPI_Datatype *) malloc( num_dtypes * sizeof(MPI_Datatype) );

    MPI_Aint extent, subExtent;
    MPI_Type_extent(datatype, &extent);

    switch (combiner) { 
    case MPI_COMBINER_NAMED: 
        // To print the specific type, we can match against the predefined forms.

        if (datatype == MPI_BYTE)                   printf( "(MPI_BYTE, %ld)", prevExtentTot);
        else if (datatype == MPI_LB)                printf( "(MPI_LB, %ld)", prevExtentTot);
        else if (datatype == MPI_PACKED)            printf( "(MPI_PACKED, %ld)", prevExtentTot);
        else if (datatype == MPI_UB)                printf( "(MPI_UB, %ld)", prevExtentTot);
        else if (datatype == MPI_CHAR)              printf( "(MPI_CHAR, %ld)", prevExtentTot);
        else if (datatype == MPI_DOUBLE)            printf( "(MPI_DOUBLE, %ld)", prevExtentTot);
        else if (datatype == MPI_FLOAT)             printf( "(MPI_FLOAT, %ld)", prevExtentTot);
        else if (datatype == MPI_INT)               printf( "(MPI_INT, %ld)", prevExtentTot );
        else if (datatype == MPI_LONG)              printf( "(MPI_LONG, %ld)", prevExtentTot);
        else if (datatype == MPI_LONG_DOUBLE)       printf( "(MPI_LONG_DOUBLE, %ld)", prevExtentTot);
        else if (datatype == MPI_LONG_LONG)         printf( "(MPI_LONG_LONG, %ld)", prevExtentTot);
        else if (datatype == MPI_LONG_LONG_INT)     printf( "(MPI_LONG_LONG_INT, %ld)", prevExtentTot);
        else if (datatype == MPI_SHORT)             printf( "(MPI_SHORT, %ld)", prevExtentTot);
        else if (datatype == MPI_SIGNED_CHAR)       printf( "(MPI_SIGNED_CHAR, %ld)", prevExtentTot);
        else if (datatype == MPI_UNSIGNED)          printf( "(MPI_UNSIGNED, %ld)", prevExtentTot);
        else if (datatype == MPI_UNSIGNED_CHAR)     printf( "(MPI_UNSIGNED_CHAR, %ld)", prevExtentTot);
        else if (datatype == MPI_UNSIGNED_LONG)     printf( "(MPI_UNSIGNED_LONG, %ld)", prevExtentTot);
        else if (datatype == MPI_UNSIGNED_LONG_LONG)printf( "(MPI_UNSIGNED_LONG_LONG, %ld)", prevExtentTot);
        else if (datatype == MPI_UNSIGNED_SHORT)    printf( "(MPI_UNSIGNED_SHORT, %ld)", prevExtentTot);
        else if (datatype == MPI_WCHAR)             printf( "(MPI_WCHAR, %ld)", prevExtentTot);

        free( array_of_ints ); 
        free( array_of_adds ); 
        free( array_of_dtypes );

        return prevExtentTot;
        break;
    case MPI_COMBINER_DUP:
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        printdatatype( array_of_dtypes[0], prevExtentTot);

        printf(", \n");

        break;
    case MPI_COMBINER_CONTIGUOUS:
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        MPI_Type_extent(array_of_dtypes[0], &subExtent); // no need to do in loop because same type

        for (i=0; i < array_of_ints[0]; i++) { 
            prevExtentTot = printdatatype( array_of_dtypes[0], prevExtentTot);
            prevExtentTot += subExtent;
            printf(", ");
        }

        break;
    case MPI_COMBINER_VECTOR:
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        MPI_Type_extent(array_of_dtypes[0], &subExtent); // no need to do in loop because same type

        printf("[");
        for (i = 0; i < array_of_ints[0]; i++) { //count
            printf( "BL : %d - ", array_of_ints[1]);
            for (j = 0; j < array_of_ints[2]; j++) { // stride
                if (j < array_of_ints[1]) { // if in blocklength
                    prevExtentTot = printdatatype( array_of_dtypes[0], prevExtentTot);
                    printf(", ");
                }
                prevExtentTot += subExtent;

            }
        }
        printf("], ");

        break;
    case MPI_COMBINER_HVECTOR:
    case MPI_COMBINER_HVECTOR_INTEGER:{
        MPI_Aint backupPrevExtent = prevExtentTot;

        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        MPI_Type_extent(array_of_dtypes[0], &subExtent); // no need to do in loop because same type

        printf("[");
        for (i = 0; i < array_of_ints[0]; i++) { //count
            printf( "BL : %d - ", array_of_ints[1]);
            for (j = 0; j < array_of_ints[1]; j++) { // blocklength
                prevExtentTot = printdatatype( array_of_dtypes[0], prevExtentTot);
                printf(", ");
                prevExtentTot += subExtent;
            }
            prevExtentTot = backupPrevExtent + array_of_adds[0]; // + stride un byte
        }
        printf("], ");

        break;
    }
    case MPI_COMBINER_INDEXED:{
        MPI_Aint tmpPrevExtent;
        int count, blocklength;
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        MPI_Type_extent(array_of_dtypes[0], &subExtent); // no need to do in loop because same type

        printf("<");
        count = array_of_ints[0];
        for (i = 0; i < count; i++) { // count
            blocklength = array_of_ints[i + 1]; // array of blocklength
            tmpPrevExtent = prevExtentTot;
            tmpPrevExtent += array_of_ints[count + 1 + i] * subExtent; // + displacement * size of block
            printf( "BL : %d - ", blocklength);
            for (j = 0; j < blocklength; j++) { // blocklength
                tmpPrevExtent = printdatatype( array_of_dtypes[0], tmpPrevExtent);
                printf(", ");
                tmpPrevExtent += subExtent;
            }
        }
        printf(">, ");

        prevExtentTot = tmpPrevExtent;

        break;
    }
    case MPI_COMBINER_HINDEXED:
    case MPI_COMBINER_HINDEXED_INTEGER:{
        MPI_Aint tmpPrevExtent;
        int count, blocklength;
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        MPI_Type_extent(array_of_dtypes[0], &subExtent); // no need to do in loop because same type

        printf("<");
        count = array_of_ints[0];
        for (i = 0; i < count; i++) { // count
            blocklength = array_of_ints[i + 1]; // array of blocklength
            tmpPrevExtent = prevExtentTot;
            tmpPrevExtent += array_of_adds[i]; // + displacement in byte
            printf( "BL : %d - ", blocklength);
            for (j = 0; j < blocklength; j++) {
                tmpPrevExtent = printdatatype( array_of_dtypes[0], tmpPrevExtent);
                printf(", ");
                tmpPrevExtent += subExtent;
            }
        }
        printf(">, ");

        prevExtentTot = tmpPrevExtent;

        break;
    }
    case MPI_COMBINER_INDEXED_BLOCK:{
        MPI_Aint tmpPrevExtent;
        int count;
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        MPI_Type_extent(array_of_dtypes[0], &subExtent); // no need to do in loop because same type

        printf("<");
        count = array_of_ints[0];
        for (i = 0; i < count; i++) { // count
            tmpPrevExtent = prevExtentTot;
            tmpPrevExtent += array_of_ints[i + 2] * subExtent; // + displacement * size of block
            printf( "BL : %d - ", array_of_ints[i + 1]);
            for (j = 0; j < array_of_ints[1]; j++) { // blocklength
                tmpPrevExtent = printdatatype( array_of_dtypes[0], tmpPrevExtent);
                printf(", ");
                tmpPrevExtent += subExtent;
            }
        }
        printf(">, ");

        prevExtentTot = tmpPrevExtent;

        break;
    }
    case MPI_COMBINER_STRUCT: 
    case MPI_COMBINER_STRUCT_INTEGER:{
        MPI_Aint tmpPrevExtent;
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        printf( "{"); 
        for (i = 0; i < array_of_ints[0]; i++) { // count
            tmpPrevExtent = prevExtentTot + array_of_adds[i]; // origin + displacement
            printf( "BL : %d - ", array_of_ints[i + 1]);
            tmpPrevExtent = printdatatype( array_of_dtypes[i], tmpPrevExtent);
            tmpPrevExtent += subExtent;
            printf(", ");
        }
        printf("}, ");

        prevExtentTot = tmpPrevExtent;

        break;
    }
    case MPI_COMBINER_SUBARRAY:
        // I don't know what is interresting to display here...
        printf("... subarray not handled ...");
        break;
    case MPI_COMBINER_DARRAY:
        // Same
        printf("... darray not handled ...");
        break;
    case MPI_COMBINER_RESIZED:
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes );

        prevExtentTot = printdatatype( array_of_dtypes[0], prevExtentTot);

        printf(", \n");

        break;
    default: 
        printf( "Unrecognized combiner type\n" ); 
    } 

    free( array_of_ints ); 
    free( array_of_adds ); 
    free( array_of_dtypes );

    return prevExtentTot;
}

void printMapDatatype(MPI_Datatype datatype) {
    MPI_Aint lb, ub;
    MPI_Type_lb(datatype, &lb);
    MPI_Type_ub(datatype, &ub);

    printf("\"(LB, %ld), ", lb);
    printdatatype(datatype, 0);
    printf("(UB, %ld)\"\n", ub);
}
MPI_Aint打印数据类型(MPI_数据类型数据类型,MPI_Aint preveExtenttot){
整数*整数的数组;
MPI_Aint*数组_of_adds;
MPI_数据类型*数据类型的数组;
int num_ints,num_adds,num_dtypes,combiner;
int i,j;
MPI\u类型\u获取\u信封(数据类型、&num\u整数、&num\u添加、&num\u数据类型、&combiner);
数组μofμints=(int*)malloc(numμints*sizeof(int));
数组_of_adds=(MPI_Aint*)malloc(num_adds*sizeof(MPI_Aint));
数组类型=(MPI_数据类型*)malloc(num_数据类型*sizeof(MPI_数据类型));
MPI维护范围、子范围;
MPI_类型_范围(数据类型和范围);
开关(组合器){
案例MPI\u组合器\u命名为:
//要打印特定类型,我们可以匹配预定义的表单。
如果(数据类型==MPI_字节)printf(((MPI_字节,%ld)”,则prevExtentTot);
否则,如果(数据类型==MPI_LB)printf(((MPI_LB,%ld)”,则为prevExtentTot);
否则,如果(数据类型==MPI_压缩)printf(((MPI_压缩,%ld)”,则为prevExtentTot);
如果(数据类型==MPI_UB)printf(((MPI_UB,%ld)”,则为prevExtentTot);
否则,如果(数据类型==MPI\u CHAR)printf(((MPI\u CHAR,%ld)”,则为prevExtentTot);
否则,如果(数据类型==MPI\U DOUBLE)printf(((MPI\U DOUBLE,%ld)”,则为prevExtentTot);
否则如果(数据类型==MPI\U浮点)printf(((MPI\U浮点,%ld)”,则为prevExtentTot);
否则,如果(数据类型==MPI_INT)printf(((MPI_INT,%ld)”,则为prevExtentTot);
否则如果(数据类型==MPI_LONG)printf(((MPI_LONG,%ld)”,则为prevExtentTot);
否则,如果(数据类型==MPI_LONG_DOUBLE)printf(((MPI_LONG_DOUBLE,%ld)”,则为prevExtentTot;
否则,如果(数据类型==MPI_LONG_LONG)printf((MPI_LONG_LONG,%ld)”,则为prevExtentTot;
否则,如果(数据类型==MPI_LONG_LONG_INT)printf(((MPI_LONG_LONG_INT,%ld)”,则为prevExtentTot;
否则,如果(数据类型==MPI_SHORT)printf(((MPI_SHORT,%ld)”,则为prevExtentTot);
else if(datatype==MPI\u SIGNED\u CHAR)printf(((MPI\u SIGNED\u CHAR,%ld)”,prevExtentTot);
否则,如果(数据类型==MPI_UNSIGNED)printf(((MPI_UNSIGNED,%ld)”,则为prevExtentTot;
else如果(数据类型==MPI_UNSIGNED_CHAR)printf((MPI_UNSIGNED_CHAR,%ld)”,则为prevExtentTot;
else如果(数据类型==MPI_UNSIGNED_LONG)printf((MPI_UNSIGNED_LONG,%ld)”,则为preveExtenttot;
else如果(数据类型==MPI\u UNSIGNED\u LONG\u LONG)printf(((MPI\u UNSIGNED\u LONG\u LONG,%ld)”,则为prevExtentTot;
else if(数据类型==MPI\u UNSIGNED\u SHORT)printf(((MPI\u UNSIGNED\u SHORT,%ld)”,prevExtentTot);
否则,如果(数据类型==MPI_WCHAR)printf(((MPI_WCHAR,%ld)”,则为prevExtentTot;
自由(整数数组);
free(数组\的\添加);
free(数组类型);
返回扩展项;
打破
案例MPI\U组合器\U DUP:
MPI\u类型\u获取\u内容(数据类型、num\u整数、num\u添加、num\u数据类型、数组\u整数、数组\u添加、数组\u数据类型);
printdatatype(数据类型[0]的数组,prevExtentTot);
printf(“,\n”);
打破
案例MPI_组合器_连续:
MPI\u类型\u获取\u内容(数据类型、num\u整数、num\u添加、num\u数据类型、数组\u整数、数组\u添加、数组\u数据类型);
MPI_Type_extent(数组_of_dtypes[0],&subExtent);//不需要在循环中执行,因为类型相同
对于(i=0;iMPI_Aint printdatatype( MPI_Datatype datatype, MPI_Aint prevExtentTot ) { 
    int *array_of_ints; 
    MPI_Aint *array_of_adds; 
    MPI_Datatype *array_of_dtypes; 
    int num_ints, num_adds, num_dtypes, combiner; 
    int i, j; 


    MPI_Type_get_envelope( datatype, &num_ints, &num_adds, &num_dtypes, &combiner ); 

    array_of_ints = (int *) malloc( num_ints * sizeof(int) ); 
    array_of_adds = (MPI_Aint *) malloc( num_adds * sizeof(MPI_Aint) ); 
    array_of_dtypes = (MPI_Datatype *) malloc( num_dtypes * sizeof(MPI_Datatype) );

    MPI_Aint extent, subExtent;
    MPI_Type_extent(datatype, &extent);

    switch (combiner) { 
    case MPI_COMBINER_NAMED: 
        // To print the specific type, we can match against the predefined forms.

        if (datatype == MPI_BYTE)                   printf( "(MPI_BYTE, %ld)", prevExtentTot);
        else if (datatype == MPI_LB)                printf( "(MPI_LB, %ld)", prevExtentTot);
        else if (datatype == MPI_PACKED)            printf( "(MPI_PACKED, %ld)", prevExtentTot);
        else if (datatype == MPI_UB)                printf( "(MPI_UB, %ld)", prevExtentTot);
        else if (datatype == MPI_CHAR)              printf( "(MPI_CHAR, %ld)", prevExtentTot);
        else if (datatype == MPI_DOUBLE)            printf( "(MPI_DOUBLE, %ld)", prevExtentTot);
        else if (datatype == MPI_FLOAT)             printf( "(MPI_FLOAT, %ld)", prevExtentTot);
        else if (datatype == MPI_INT)               printf( "(MPI_INT, %ld)", prevExtentTot );
        else if (datatype == MPI_LONG)              printf( "(MPI_LONG, %ld)", prevExtentTot);
        else if (datatype == MPI_LONG_DOUBLE)       printf( "(MPI_LONG_DOUBLE, %ld)", prevExtentTot);
        else if (datatype == MPI_LONG_LONG)         printf( "(MPI_LONG_LONG, %ld)", prevExtentTot);
        else if (datatype == MPI_LONG_LONG_INT)     printf( "(MPI_LONG_LONG_INT, %ld)", prevExtentTot);
        else if (datatype == MPI_SHORT)             printf( "(MPI_SHORT, %ld)", prevExtentTot);
        else if (datatype == MPI_SIGNED_CHAR)       printf( "(MPI_SIGNED_CHAR, %ld)", prevExtentTot);
        else if (datatype == MPI_UNSIGNED)          printf( "(MPI_UNSIGNED, %ld)", prevExtentTot);
        else if (datatype == MPI_UNSIGNED_CHAR)     printf( "(MPI_UNSIGNED_CHAR, %ld)", prevExtentTot);
        else if (datatype == MPI_UNSIGNED_LONG)     printf( "(MPI_UNSIGNED_LONG, %ld)", prevExtentTot);
        else if (datatype == MPI_UNSIGNED_LONG_LONG)printf( "(MPI_UNSIGNED_LONG_LONG, %ld)", prevExtentTot);
        else if (datatype == MPI_UNSIGNED_SHORT)    printf( "(MPI_UNSIGNED_SHORT, %ld)", prevExtentTot);
        else if (datatype == MPI_WCHAR)             printf( "(MPI_WCHAR, %ld)", prevExtentTot);

        free( array_of_ints ); 
        free( array_of_adds ); 
        free( array_of_dtypes );

        return prevExtentTot;
        break;
    case MPI_COMBINER_DUP:
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        printdatatype( array_of_dtypes[0], prevExtentTot);

        printf(", \n");

        break;
    case MPI_COMBINER_CONTIGUOUS:
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        MPI_Type_extent(array_of_dtypes[0], &subExtent); // no need to do in loop because same type

        for (i=0; i < array_of_ints[0]; i++) { 
            prevExtentTot = printdatatype( array_of_dtypes[0], prevExtentTot);
            prevExtentTot += subExtent;
            printf(", ");
        }

        break;
    case MPI_COMBINER_VECTOR:
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        MPI_Type_extent(array_of_dtypes[0], &subExtent); // no need to do in loop because same type

        printf("[");
        for (i = 0; i < array_of_ints[0]; i++) { //count
            printf( "BL : %d - ", array_of_ints[1]);
            for (j = 0; j < array_of_ints[2]; j++) { // stride
                if (j < array_of_ints[1]) { // if in blocklength
                    prevExtentTot = printdatatype( array_of_dtypes[0], prevExtentTot);
                    printf(", ");
                }
                prevExtentTot += subExtent;

            }
        }
        printf("], ");

        break;
    case MPI_COMBINER_HVECTOR:
    case MPI_COMBINER_HVECTOR_INTEGER:{
        MPI_Aint backupPrevExtent = prevExtentTot;

        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        MPI_Type_extent(array_of_dtypes[0], &subExtent); // no need to do in loop because same type

        printf("[");
        for (i = 0; i < array_of_ints[0]; i++) { //count
            printf( "BL : %d - ", array_of_ints[1]);
            for (j = 0; j < array_of_ints[1]; j++) { // blocklength
                prevExtentTot = printdatatype( array_of_dtypes[0], prevExtentTot);
                printf(", ");
                prevExtentTot += subExtent;
            }
            prevExtentTot = backupPrevExtent + array_of_adds[0]; // + stride un byte
        }
        printf("], ");

        break;
    }
    case MPI_COMBINER_INDEXED:{
        MPI_Aint tmpPrevExtent;
        int count, blocklength;
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        MPI_Type_extent(array_of_dtypes[0], &subExtent); // no need to do in loop because same type

        printf("<");
        count = array_of_ints[0];
        for (i = 0; i < count; i++) { // count
            blocklength = array_of_ints[i + 1]; // array of blocklength
            tmpPrevExtent = prevExtentTot;
            tmpPrevExtent += array_of_ints[count + 1 + i] * subExtent; // + displacement * size of block
            printf( "BL : %d - ", blocklength);
            for (j = 0; j < blocklength; j++) { // blocklength
                tmpPrevExtent = printdatatype( array_of_dtypes[0], tmpPrevExtent);
                printf(", ");
                tmpPrevExtent += subExtent;
            }
        }
        printf(">, ");

        prevExtentTot = tmpPrevExtent;

        break;
    }
    case MPI_COMBINER_HINDEXED:
    case MPI_COMBINER_HINDEXED_INTEGER:{
        MPI_Aint tmpPrevExtent;
        int count, blocklength;
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        MPI_Type_extent(array_of_dtypes[0], &subExtent); // no need to do in loop because same type

        printf("<");
        count = array_of_ints[0];
        for (i = 0; i < count; i++) { // count
            blocklength = array_of_ints[i + 1]; // array of blocklength
            tmpPrevExtent = prevExtentTot;
            tmpPrevExtent += array_of_adds[i]; // + displacement in byte
            printf( "BL : %d - ", blocklength);
            for (j = 0; j < blocklength; j++) {
                tmpPrevExtent = printdatatype( array_of_dtypes[0], tmpPrevExtent);
                printf(", ");
                tmpPrevExtent += subExtent;
            }
        }
        printf(">, ");

        prevExtentTot = tmpPrevExtent;

        break;
    }
    case MPI_COMBINER_INDEXED_BLOCK:{
        MPI_Aint tmpPrevExtent;
        int count;
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        MPI_Type_extent(array_of_dtypes[0], &subExtent); // no need to do in loop because same type

        printf("<");
        count = array_of_ints[0];
        for (i = 0; i < count; i++) { // count
            tmpPrevExtent = prevExtentTot;
            tmpPrevExtent += array_of_ints[i + 2] * subExtent; // + displacement * size of block
            printf( "BL : %d - ", array_of_ints[i + 1]);
            for (j = 0; j < array_of_ints[1]; j++) { // blocklength
                tmpPrevExtent = printdatatype( array_of_dtypes[0], tmpPrevExtent);
                printf(", ");
                tmpPrevExtent += subExtent;
            }
        }
        printf(">, ");

        prevExtentTot = tmpPrevExtent;

        break;
    }
    case MPI_COMBINER_STRUCT: 
    case MPI_COMBINER_STRUCT_INTEGER:{
        MPI_Aint tmpPrevExtent;
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes ); 

        printf( "{"); 
        for (i = 0; i < array_of_ints[0]; i++) { // count
            tmpPrevExtent = prevExtentTot + array_of_adds[i]; // origin + displacement
            printf( "BL : %d - ", array_of_ints[i + 1]);
            tmpPrevExtent = printdatatype( array_of_dtypes[i], tmpPrevExtent);
            tmpPrevExtent += subExtent;
            printf(", ");
        }
        printf("}, ");

        prevExtentTot = tmpPrevExtent;

        break;
    }
    case MPI_COMBINER_SUBARRAY:
        // I don't know what is interresting to display here...
        printf("... subarray not handled ...");
        break;
    case MPI_COMBINER_DARRAY:
        // Same
        printf("... darray not handled ...");
        break;
    case MPI_COMBINER_RESIZED:
        MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes, array_of_ints, array_of_adds, array_of_dtypes );

        prevExtentTot = printdatatype( array_of_dtypes[0], prevExtentTot);

        printf(", \n");

        break;
    default: 
        printf( "Unrecognized combiner type\n" ); 
    } 

    free( array_of_ints ); 
    free( array_of_adds ); 
    free( array_of_dtypes );

    return prevExtentTot;
}

void printMapDatatype(MPI_Datatype datatype) {
    MPI_Aint lb, ub;
    MPI_Type_lb(datatype, &lb);
    MPI_Type_ub(datatype, &ub);

    printf("\"(LB, %ld), ", lb);
    printdatatype(datatype, 0);
    printf("(UB, %ld)\"\n", ub);
}