【发布时间】:2019-09-18 05:03:52
【问题描述】:
是否可以在具有更多处理器的单个输出文件上写入数据。我的意思是考虑一些处理器有一部分数据(例如矩阵),整个矩阵应该写在一个输出文件中。是否有可能每个处理器并行编写自己的部分(同时不是一个接一个)?
【问题讨论】:
标签: parallel-processing mpi writefile
是否可以在具有更多处理器的单个输出文件上写入数据。我的意思是考虑一些处理器有一部分数据(例如矩阵),整个矩阵应该写在一个输出文件中。是否有可能每个处理器并行编写自己的部分(同时不是一个接一个)?
【问题讨论】:
标签: parallel-processing mpi writefile
是的,这绝对有可能,而且 MPI 为您提供了所有工具。
great introduction to MPI I/O 已在 cmets 中链接。我只是举一个最小的例子来演示它;
#include <stdint.h>
#include <mpi.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
const int N = 1024ll * 1024 * 256 * 12;
const MPI_Datatype MPI_T = MPI_UINT64_T;
typedef uint64_t T;
const char* filename = "mpi.out";
int main() {
MPI_Init(NULL, NULL);
int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
assert(N % size == 0);
T* my_part = calloc(N / size, sizeof(T));
for (size_t i = 0; i < N / size; i++)
my_part[i] = i + rank * (N / size);
MPI_File fh;
MPI_File_open(MPI_COMM_WORLD, filename,
MPI_MODE_WRONLY | MPI_MODE_CREATE, MPI_INFO_NULL,
&fh);
MPI_File_set_view(fh, rank * (N / size) * sizeof(T), MPI_T, MPI_T,
"native", MPI_INFO_NULL);
MPI_Barrier(MPI_COMM_WORLD);
double begin = MPI_Wtime();
MPI_File_write_all(fh, my_part, N / size, MPI_T, MPI_STATUS_IGNORE);
MPI_Barrier(MPI_COMM_WORLD);
double duration = MPI_Wtime() - begin;
if (rank == 0)
printf("Wrote %llu B in %f s, %f GiB/s\n",
N * sizeof(T), duration,
N * sizeof(T) / (duration * 1024 * 1024 * 1024));
MPI_File_close(&fh);
MPI_Finalize();
}
通过非常小的调整(将条带化大小设置为 12)和 12 个等级,这在大约 7.3 GiB/s 的 Lustre 上获得了相当合理的性能。请注意,这超出了系统使用的 4xFDR InfiniBand 的原始吞吐量。
通常,您会在此类文件视图中使用自定义数据类型,或者甚至在 MPI I/O 之上工作的更高级的 I/O 库(例如 HDF5)。获得最佳性能可能需要针对特定站点进行一些调整。
实际上,这足以知道,但参考 user3666197 对另一个答案的讨论,还有一些更挑剔的细节:
这段代码 sn-p 以相当高级的抽象表示并发文件写入。通过在具有并行文件系统的 HPC 系统上执行此代码,您可以获得真正的并行 I/O。在经过良好调整的配置中,从不同等级写入的字节完全有可能遵循完全不同的路径并最终到达不同存储服务器的不同磁盘上——所有这些都是并行的。在你的代码中重要的是表达并发性——然后你应用调优来确保它运行良好——这意味着允许存储系统高效地并行执行它。
【讨论】:
Q:是否有可能每个处理器并行编写自己的部分(同时不是一个接一个)?
不,不是。写作是以纯[SERIAL] 的方式将原子信息(位到磁带,字符到文件抽象)放入的过程。
如果有疑问,请拿起 5 支铅笔(我做不到,所以想象一支可以)并尝试在纸上写一个字(由于“写作过程”相关情况——我们如何写的奇点),在这个简化的例子中,不可能“写”出 5 个独立的词,即不同的词。
类似地,在其他形式的插图中 - 如果你有一台打字机(希望它不是那么古老的想象) - 可以得到 5 份相同的纯 -[SERIAL] 字符序列(感谢使用填充在这 5 张办公用纸之间的 4 张复写纸),但这些副本都不会与原件不同 - 所以这些不是独立的(就像这些在 true-[PARALLEL] 过程中一样)但只是一组副本,它可以有效地利用时间和资源来制作一些文书工作,以便在某些管理矩阵中发送 1 个原件 + 4 个副本,但不是 true-[PARALLEL] 写入的示例。
最后但并非最不重要的一点是,任何尝试同时使用比一个且仅一个更多的手指在打字机上打字(这会将纯-[SERIAL] 字符序列打印在纸上)都会产生机械卡纸,因为机械打字的过程依赖于一个单一的点,一个字符通过一个墨水横幅的撞击被打印到纸上。
现代文件系统远非这种微不足道的原型,但具有类似的概念,即生成和维护一个纯[SERIAL] 表示的字符序列。即使可以打开更多的文件句柄来“进入”这个字符序列,但这并不意味着一个人有机会反序列化文件 I/O 操作,一次执行的次数越少(由于磁盘磁头不会同时出现在磁盘存储的多个不同位置(磁带设备较少),而且几乎随机访问的设备(如 SSD 等)也不会如此疯狂,他们失去了对低级属性的控制(磨损均衡、电梯优化、功率限制和类似的低级设备技巧)。
【讨论】: