3

考虑以下简单程序,它将所有等级大于零的进程的等级写入文件:

#include <mpi.h>

int main() {
    MPI_Init(NULL, NULL);

    int world_rank, world_size;
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);

    MPI_Offset offset;
    MPI_Status status;
    MPI_File fh;

    MPI_File_open(MPI_COMM_WORLD, "myfile", MPI_MODE_CREATE | MPI_MODE_WRONLY,
            MPI_INFO_NULL, &fh);
    
    offset = world_rank * sizeof(int);

    if (world_rank > 0) {
        MPI_File_write_at(fh, offset, &world_rank, 1, MPI_INT, &status);
    }

    MPI_File_close(&fh);

    MPI_Finalize();

    return 0;
}

我们在 4 个进程上编译并运行它

mpic++ main.cpp
mpirun --oversubscribe -n 4 a.out 

我们检查写入的文件hexdump -C myfile

00000000  00 00 00 00 01 00 00 00  02 00 00 00 03 00 00 00  |................|
00000010

现在,我从未对第一个整数也就是前 4 个字节进行写调用,但它们为零。

可以确定那些总是零吗?

4

1 回答 1

2

MPI_File_write_at将数据作为binary data. 然后,当您运行命令时hexdump -C myfile,该命令将相应地显示数据,第一个4 bytesoffset。那些第一个字节不是每个 si二进制数据的一部分,而是hexdump -C myfile出于可读性目的而添加的。

十六进制00000010表示10000二进制和16十进制。如果你看你的第一行,忽略前 4 个字节,:

  4 bytes   4 bytes      4 bytes      4 bytes       4 bytes 
00000000 | 00 00 00 00  01 00 00 00  02 00 00 00   03 00 00 00
00000010 |

您有16(4x4)字节,因此下一行以00000010.

我可以确定那些总是零吗?

就标准而言,我没有在那里找到,明确指出如果跳过文件的开头offset > 0,则 MPI 实现将用零填充该空白。例如,对于我正在使用的 MPI 版本(Open MPI 1.8.8),如果我将您的代码修改为:

 if (world_rank == 3) {
    MPI_File_write_at(fh, offset, &world_rank, 1, MPI_INT, &status);
}

我从以下输出hexdump -C myfile

00000000  00 00 00 00 00 00 00 00  00 00 00 00 03 00 00 00  |................|
00000010

因此,对于我正在使用的 MPI 版本,显然是您的,它用零初始化。

尽管如此,除非可以找到可靠的来源(我没有找到)明确指出在您的情况下前 4 个字节将始终为零,否则我建议不要在这方面做出任何假设。尽管如此,无论如何,人们不应该关心不是由进程写入的文件内容部分。

编辑:来自“开放 MPI 邮件列表”的澄清:

通常,由 MPI IO 接口写入的文件内容将是特定于实现的。

于 2020-12-11T19:03:40.750 回答