我的工作假设MPI流程从开始到结束都在独立且独特的数据上运行,即使在同一台机器上也是如此。但是我的代码,我希望每个MPI进程都有一个全局对象:
class global { // the class };
extern global obj;
global obj;
int main( int argc, char * argv[] ) {
MPI_Init();
// determine rank
std::cout << rank << " global object is at " << &obj << std::endl;
MPI_Finalize();
}
使用-np 2,结果为:
0 global object is at 0x620740
1 global object is at 0x620740
这可能是分段错误或其他错误的来源,其中两个MPI进程在同一台机器上访问相同的内存地址以获取其自己的全局对象吗?
编辑:我应该提一下,我的意图中的'全球'并非在所有MPI流程中全球化,而是在每个单独的MPI流程中全球化。
答案 0 :(得分:7)
MPI使用相同的可执行文件启动多个进程。通常,这会导致这些进程具有相同的初始内存布局,只有堆栈的位置和不同共享库映射的位置可能不同。在您的情况下,obj
是一个未初始化的静态对象,因此放在BSS部分中,该部分通常位于初始化数据部分之后。预先知道数据量和BSS部分的位置 - 这些由链接器修复。因此,obj
在从该可执行文件创建的每个进程中具有相同的位置。
这对MPI来说不是问题,因为每个进程都有自己的虚拟内存空间,并且您看到的地址是虚拟地址,仅在相应进程的虚拟内存空间中有效。换句话说,等级0中的0x620740
和等级1中的0x620740
在物理内存中是完全不同的位置,因为它们都指向两个不同虚拟内存空间中的相同位置。
通常,MPI没有全局(或共享)对象的概念,因为通过假设,MPI作业中的每个进程只能访问其自己的隔离内存空间。实际上,进程可以(并且它们通常会)在同一物理节点上运行时共享内存(例如,当进程在多核,多处理器或其他类型的共享内存机器上运行时,MPI通常使用共享内存发送消息),但除非您已经采取特殊步骤将obj
放入专门创建的共享内存段中,它将不会被共享。