9.5. 已移除的MPI结构

从v4.0.0版本开始,Open MPI默认会从mpi.h中移除那些在1996年MPI-2.0标准中已被弃用,并最终在MPI-3.0标准(2012年)中被移除的MPI符号原型。

具体来说,以下符号(以MPI语言中立名称指定)默认不再在mpi.h中进行原型声明:

注意

您可能需要向右滚动查看以下表格。

移除的符号

(点击查看详情,见下方)

替换为

(点击跳转至对应手册页)

已弃用

已移除

MPI_ADDRESS

MPI_GET_ADDRESS

MPI-2.0 (1996)

MPI-3.0 (2012)

MPI_ERRHANDLER_CREATE

MPI_COMM_CREATE_ERRHANDLER

MPI-2.0 (1996)

MPI-3.0 (2012)

MPI_ERRHANDLER_GET

MPI_COMM_GET_ERRHANDLER

MPI-2.0 (1996)

MPI-3.0 (2012)

MPI_ERRHANDLER_SET

MPI_COMM_SET_ERRHANDLER

MPI-2.0 (1996)

MPI-3.0 (2012)

MPI_TYPE_EXTENT

MPI_TYPE_GET_EXTENT

MPI-2.0 (1996)

MPI-3.0 (2012)

MPI_TYPE_HINDEXED

MPI_TYPE_CREATE_HINDEXED

MPI-2.0 (1996)

MPI-3.0 (2012)

MPI_TYPE_HVECTOR

MPI_TYPE_CREATE_HVECTOR

MPI-2.0 (1996)

MPI-3.0 (2012)

MPI_TYPE_LB

MPI_TYPE_GET_EXTENT

MPI-2.0 (1996)

MPI-3.0 (2012)

MPI_TYPE_STRUCT

MPI_TYPE_CREATE_STRUCT

MPI-2.0 (1996)

MPI-3.0 (2012)

MPI_TYPE_UB

MPI_TYPE_GET_EXTENT

MPI-2.0 (1996)

MPI-3.0 (2012)

MPI_LB

MPI_TYPE_CREATE_RESIZED

MPI-2.0 (1996)

MPI-3.0 (2012)

MPI_UB

MPI_TYPE_CREATE_RESIZED

MPI-2.0 (1996)

MPI-3.0 (2012)

MPI_COMBINED_HINDEXED_INTEGER

MPI_COMBINER_HINDEXED

MPI-2.0 (1996)

MPI-3.0 (2012)

MPI_COMBINED_HVECTOR_INTEGER

MPI_COMBINER_HVECTOR

MPI-2.0 (1996)

MPI-3.0 (2012)

MPI_COMBINED_STRUCT_INTEGER

MPI_COMBINER_STRUCT

MPI-2.0 (1996)

MPI-3.0 (2012)

MPI_HANDLER_FUNCTION

MPI_COMM_ERRHANDLER_FUNCTION

MPI-2.0 (1996)

MPI-3.0 (2012)

尽管这些符号不再在mpi.h中声明原型,但它们仍然存在于Open MPI v5.0.x的MPI库中。这使得传统的MPI应用程序能够成功链接并运行于Open MPI v5.0.x,尽管它们将无法通过编译

此外,MPI C++接口在2.2版本中被弃用,随后在MPI-3.0中被移除。从v5.0.0开始,Open MPI不再支持C++接口。希望继续使用MPI C++接口的用户需要使用旧版本的Open MPI。

警告

Open MPI团队强烈建议所有MPI应用程序开发者停止使用这些早在20多年前就被弃用的结构,它们最终在MPI-3.0版本(2012年)中从MPI规范里移除了。

本类别下的常见问题解答条目展示了如何更新您的应用程序,以停止使用这些已移除的符号。

综上所述,如果您无法立即更新应用程序以停止使用这些已移除的MPI-1符号,您可以通过配置Open MPI时使用--enable-mpi1-compatibility标志来在mpi.h中重新启用它们。

注意

Open MPI的未来版本可能会完全移除这些符号。

9.5.1. 为什么Open MPI会导致MPI应用程序编译失败?

Open MPI开发者社区决定从Open MPI v4.0.x系列开始,从mpi.h中移除已弃用函数的原型,原因如下:

  1. 第一组符号自1996年起已被弃用。现在是时候提醒那些仍在无意中使用这些已移除符号的开发者了。

  2. MPI论坛在2012年从MPI-3.0规范中移除了大量符号。这表明论坛自身也认识到这些被移除的符号已不再需要。

  3. MPI 2.2和MPI 4.0中已弃用更多函数,预计未来MPI版本还将弃用并移除其他函数。为了尽可能减少混淆并严格遵循MPI规范,这对开发者和最终用户都有利。

  4. 请注意,Open MPI 并未完全移除这些已废弃的符号:我们只是让访问它们变得稍微麻烦一些。这是为了提高开发者意识,以便MPI应用程序开发者能更新他们的应用(这很简单!)。

简而言之:未来某天能够最终从Open MPI中移除这些已废弃符号的唯一方法是设置一个“宽限期”,在此期间让MPI应用程序开发者:a) 意识到他们正在使用已废弃的符号,b) 学会如何更新他们的应用程序。

我们Open MPI开发团队理解,您的MPI应用程序无法在Open MPI上编译可能是个令人不快的意外。对此我们深表歉意。

我们的意图很简单,就是利用这次小冲击来提高大家的意识,并借此作为一个教育机会,向您展示如何更新您的应用程序(或指引您友好的社区MPI应用程序开发者参考此FAQ),以停止使用这些已移除的MPI符号。

感谢!

9.5.2. 停止使用MPI_ADDRESS

在C语言中,唯一变化的是函数名称: MPI_Address()MPI_Get_address()。其他部分无需修改:

char buffer[30];
MPI_Aint address;

// Old way
MPI_Address(buffer, &address);

// New way
MPI_Get_address(buffer, &address);

在Fortran中,参数类型从INTEGER更改为INTEGER(KIND=MPI_ADDRESS_KIND),以便能够容纳更大的值(例如64位指针):

USE mpi
REAL buffer
INTEGER ierror
INTEGER old_address
INTEGER(KIND = MPI_ADDRESS_KIND) new_address

! Old way
CALL MPI_ADDRESS(buffer, old_address, ierror)

! New way
CALL MPI_GET_ADDRESS(buffer, new_address, ierror)

9.5.3. 停止使用MPI_ERRHANDLER_CREATE

在C语言中,实际上唯一改变的是函数名称:MPI_Errhandler_create()MPI_Comm_create_errhandler()

从技术上讲,第一个参数的类型也发生了变化 (MPI_Handler_functionMPI_Comm_errhandler_function), 但大多数应用程序不会直接使用这个类型,甚至可能不会注意到这个变化。

void my_errhandler_function(MPI_Comm *comm, int *code, ...)
{
    // Do something useful to handle the error
}

void some_function(void)
{
    MPI_Errhandler my_handler;

    // Old way
    MPI_Errhandler_create(my_errhandler_function, &my_handler);

    // New way
    MPI_Comm_create_errhandler(my_errhandler_function, &my_handler);
}

在Fortran中,仅子程序名称发生了变化: MPI_ERRHANDLER_CREATEMPI_COMM_CREATE_ERRHANDLER

USE mpi
EXTERNAL my_errhandler_function
INTEGER ierror
INTEGER my_handler

! Old way
CALL MPI_ERRHANDLER_CREATE(my_errhandler_function, my_handler, ierror)

! New way
CALL MPI_COMM_CREATE_ERRHANDLER(my_errhandler_function, my_handler, ierror)

9.5.4. 停止使用MPI_ERRHANDLER_GET

在C和Fortran中,唯一发生变化的是名称:MPI_ERRHANDLER_GETMPI_COMM_GET_ERRHANDLER

所有参数类型保持不变。

9.5.5. 停止使用MPI_ERRHANDLER_SET

在C和Fortran中,关于MPI_ERRHANDLER_SET唯一改变的是名称:MPI_ERRHANDLER_SETMPI_COMM_SET_ERRHANDLER

所有参数类型保持不变。

9.5.6. 停止使用MPI_TYPE_HINDEXED

在C和Fortran中,实际上唯一的变化是函数名称:MPI_TYPE_HINDEXEDMPI_TYPE_CREATE_HINDEXED

在C语言中,新函数的两个数组参数也带有const属性,但大多数应用程序不会注意到这个区别。

所有其他参数类型保持不变。

int count = 2;
int block_lengths[] = { 1, 2 };
MPI_Aint displacements[] = { 0, sizeof(int) };
MPI_Datatype newtype;

// Old way
MPI_Type_hindexed(count, block_lengths, displacements, MPI_INT, &newtype);

// New way
MPI_Type_create_hindexed(count, block_lengths, displacements, MPI_INT, &newtype);

9.5.7. 停止使用MPI_TYPE_HVECTOR

在C和Fortran中,唯一的变化是函数名称: MPI_TYPE_HVECTORMPI_TYPE_CREATE_HVECTOR

所有参数类型保持不变。

9.5.8. 停止使用MPI_TYPE_STRUCT

在C和Fortran中,实际上唯一的变化是函数名称:MPI_TYPE_STRUCTMPI_TYPE_CREATE_STRUCT

在C语言中,新函数还在三个数组参数上添加了const属性,但大多数应用程序不会注意到这个差异。

所有其他参数类型保持不变。

int count = 2;
int block_lengths[] = { 1, 2 };
MPI_Aint displacements[] = { 0, sizeof(int) };
MPI_Datatype datatypes[] = { MPI_INT, MPI_DOUBLE };
MPI_Datatype newtype;

// Old way
MPI_Type_struct(count, block_lengths, displacements, datatypes, &newtype);

// New way
MPI_Type_create_struct(count, block_lengths, displacements, datatypes, &newtype);

9.5.9. 停止使用MPI_TYPE_EXTENT

在C和Fortran中,MPI_TYPE_EXTENT函数已被略有不同的MPI_TYPE_GET_EXTENT函数取代:新函数还会返回下界值。

MPI_Aint lb;
MPI_Aint extent;

// Old way
MPI_Type_extent(MPI_INT, &extent);

// New way
MPI_Type_get_extent(MPI_INT, &lb, &extent);

9.5.10. 停止使用MPI_TYPE_LB

在C和Fortran中,MPI_TYPE_LB函数已被功能略有不同的MPI_TYPE_GET_EXTENT函数取代:新函数还会返回范围值。

MPI_Aint lb;
MPI_Aint extent;

// Old way
MPI_Type_lb(MPI_INT, &lb);

// New way
MPI_Type_get_extent(MPI_INT, &lb, &extent);

9.5.11. 停止使用MPI_TYPE_UB

在C和Fortran中,MPI_TYPE_UB函数已被略有不同的MPI_TYPE_GET_EXTENT函数取代:新函数返回下界和范围,可用于计算上界。

MPI_Aint lb, ub;
MPI_Aint extent;

// Old way
MPI_Type_ub(MPI_INT, &ub);

// New way
MPI_Type_get_extent(MPI_INT, &lb, &extent);
ub = lb + extent

注意在调用MPI_Type_get_extent()后进行的ub计算。

9.5.12. 停止使用MPI_LB/MPI_UB

在MPI-2.0中,MPI_LBMPI_UB位置标记已完全被MPI_TYPE_CREATE_RESIZED取代。

在MPI-2.0之前,MPI_UBMPI_LB原本设计用于作为MPI_TYPE_STRUCT的输入(该函数本身已被弃用并重命名为MPI_TYPE_CREATE_STRUCT)。现在可以通过MPI_TYPE_CREATE_RESIZED实现相同的最终效果。例如,使用旧方法:

int count = 3;
int block_lengths[] = { 1, 1, 1 };
MPI_Aint displacements[] = { -2, 0, 10 };
MPI_Datatype datatypes[] = { MPI_LB, MPI_INT, MPI_UB };
MPI_Datatype newtype;

MPI_Type_struct(count, block_lengths, displacements, datatypes, &newtype);
MPI_Type_commit(&newtype);

MPI_Aint ub, lb, extent;
MPI_Type_lb(newtype, &lb);
MPI_Type_ub(newtype, &ub);
MPI_Type_extent(newtype, &extent);
printf("OLD: LB=%d, UB=%d, extent=%d\n",
       lb, ub, extent);

如果我们运行上述代码,将得到如下输出:

OLD: LB=-2, UB=10, extent=12

MPI_TYPE_RESIZED 函数允许我们直接设置任意数据类型的下界和范围(间接设置上界),而无需配置数组或计算调用 MPI_TYPE_CREATE_STRUCT 所需的位移量。

除了printf语句外,以下示例与之前的示例完全等效(关于MPI_TYPE_UBMPI_TYPE_GET_EXTENT的映射,请参阅see the MPI_TYPE_UB section):

MPI_Datatype newtype;

MPI_Type_create_resized(MPI_INT, -2, 12, &newtype);
MPI_Type_commit(&newtype);

MPI_Aint ub, lb, extent;
MPI_Type_get_extent(newtype, &lb, &extent);
ub = lb + extent;
printf("NEW: LB=%d, UB=%d, extent=%d\n",
       lb, ub, extent);

如果我们运行上述代码,将得到如下输出:

NEW: LB=-2, UB=10, extent=12

9.5.13. 停止使用MPI_COMBINER_HINDEXED_INTEGER、MPI_COMBINER_HVECTOR_INTEGER和MPI_COMBINER_STRUCT_INTEGER

MPI_COMBINER_HINDEXED_INTEGERMPI_COMBINER_HVECTOR_INTEGERMPI_COMBINER_STRUCT_INTEGER常量之前可以从MPI_TYPE_GET_ENVELOPE中返回。

从MPI-3.0开始,这些值将不再返回。相反,它们只会返回相同的名称,但不再带有_INTEGER后缀。具体来说:

  • MPI_COMBINER_HINDEXED_INTEGERMPI_COMBINER_HINDEXED

  • MPI_COMBINER_HVECTOR_INTEGERMPI_COMBINER_HVECTOR

  • MPI_COMBINER_STRUCT_INTEGERMPI_COMBINER_STRUCT

如果你的Fortran代码使用了任何带有_INTEGER后缀的名称,你可以直接删除_INTEGER后缀。

9.5.14. 停止使用MPI_Handler_function

MPI_Handler_function C类型仅用于已弃用/移除的函数MPI_Errhandler_create()中,具体描述见MPI_ERRHANDLER_CREATE章节

大多数MPI应用程序可能根本不会使用这种类型。但如果确实需要,它们可以简单地使用新的、完全等效的类型名称(即返回类型、参数数量和类型均未改变):MPI_Comm_errhandler_function

void my_errhandler_function(MPI_Comm *comm, int *code, ...)
{
    // Do something useful to handle the error
}

void some_function(void)
{
    // Old way
    MPI_Handler_function *old_ptr = my_errhandler_function;

    // New way
    MPI_Comm_errhandler_function *new_ptr = my_errhandler_function;
}

MPI_Handler_function 类型在 Fortran 绑定中完全未被使用。