9.5. 已移除的MPI结构
从v4.0.0版本开始,Open MPI默认会从mpi.h中移除那些在1996年MPI-2.0标准中已被弃用,并最终在MPI-3.0标准(2012年)中被移除的MPI符号原型。
具体来说,以下符号(以MPI语言中立名称指定)默认不再在mpi.h中进行原型声明:
注意
您可能需要向右滚动查看以下表格。
移除的符号 (点击查看详情,见下方) |
替换为 (点击跳转至对应手册页) |
已弃用 |
已移除 |
|---|---|---|---|
MPI-2.0 (1996) |
MPI-3.0 (2012) |
||
MPI-2.0 (1996) |
MPI-3.0 (2012) |
||
MPI-2.0 (1996) |
MPI-3.0 (2012) |
||
MPI-2.0 (1996) |
MPI-3.0 (2012) |
||
MPI-2.0 (1996) |
MPI-3.0 (2012) |
||
MPI-2.0 (1996) |
MPI-3.0 (2012) |
||
MPI-2.0 (1996) |
MPI-3.0 (2012) |
||
MPI-2.0 (1996) |
MPI-3.0 (2012) |
||
MPI-2.0 (1996) |
MPI-3.0 (2012) |
||
MPI-2.0 (1996) |
MPI-3.0 (2012) |
||
MPI-2.0 (1996) |
MPI-3.0 (2012) |
||
MPI-2.0 (1996) |
MPI-3.0 (2012) |
||
MPI-2.0 (1996) |
MPI-3.0 (2012) |
||
MPI-2.0 (1996) |
MPI-3.0 (2012) |
||
MPI-2.0 (1996) |
MPI-3.0 (2012) |
||
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中移除已弃用函数的原型,原因如下:
第一组符号自1996年起已被弃用。现在是时候提醒那些仍在无意中使用这些已移除符号的开发者了。
MPI论坛在2012年从MPI-3.0规范中移除了大量符号。这表明论坛自身也认识到这些被移除的符号已不再需要。
MPI 2.2和MPI 4.0中已弃用更多函数,预计未来MPI版本还将弃用并移除其他函数。为了尽可能减少混淆并严格遵循MPI规范,这对开发者和最终用户都有利。
请注意,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_function → MPI_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_CREATE → MPI_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_GET → MPI_COMM_GET_ERRHANDLER。
所有参数类型保持不变。
9.5.5. 停止使用MPI_ERRHANDLER_SET
在C和Fortran中,关于MPI_ERRHANDLER_SET唯一改变的是名称:MPI_ERRHANDLER_SET → MPI_COMM_SET_ERRHANDLER。
所有参数类型保持不变。
9.5.6. 停止使用MPI_TYPE_HINDEXED
在C和Fortran中,实际上唯一的变化是函数名称:MPI_TYPE_HINDEXED → MPI_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_HVECTOR → MPI_TYPE_CREATE_HVECTOR。
所有参数类型保持不变。
9.5.8. 停止使用MPI_TYPE_STRUCT
在C和Fortran中,实际上唯一的变化是函数名称:MPI_TYPE_STRUCT → MPI_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_LB和MPI_UB位置标记已完全被MPI_TYPE_CREATE_RESIZED取代。
在MPI-2.0之前,MPI_UB和MPI_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_UB到MPI_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_INTEGER、MPI_COMBINER_HVECTOR_INTEGER和MPI_COMBINER_STRUCT_INTEGER常量之前可以从MPI_TYPE_GET_ENVELOPE中返回。
从MPI-3.0开始,这些值将不再返回。相反,它们只会返回相同的名称,但不再带有_INTEGER后缀。具体来说:
MPI_COMBINER_HINDEXED_INTEGER→MPI_COMBINER_HINDEXEDMPI_COMBINER_HVECTOR_INTEGER→MPI_COMBINER_HVECTORMPI_COMBINER_STRUCT_INTEGER→MPI_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 绑定中完全未被使用。