使用并行 I/O 复制大数据文件
Copy large data file using parallel I/O
我有一个相当大的数据集,大约 1.41 亿行,格式为 .csv。我想在 C++ 中使用 MPI 命令来复制和操作一些列,但我是 C++ 和 MPI 的新手。
到目前为止我的代码是这样的
#include <stdio.h>
#include "mpi.h"
using namespace std;
int main(int argc, char **argv)
{
int i, rank, nprocs, size, offset, nints, bufsize, N=4;
MPI_File fp, fpwrite; // File pointer
MPI_Status status;
MPI_Offset filesize;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_File_get_size(fp, &filesize);
int buf[N];
for (i = 0; i<N; i++)
buf[i] = i;
offset = rank * (N/size)*sizeof(int);
MPI_File_open(MPI_COMM_WORLD, "new.csv", MPI_MODE_RDONLY, MPI_INFO_NULL, &fp);
MPI_File_open(MPI_COMM_WORLD, "Ntest.csv", MPI_MODE_CREATE|MPI_MODE_WRONLY, MPI_INFO_NULL, &fpwrite);
MPI_File_read(fp, buf, N, MPI_INT, &status);
// printf("\nrank: %d, buf[%d]: %d\n", rank, rank*bufsize, buf[0]);
printf("My rank is: %d\n", rank);
MPI_File_write_at(fpwrite, offset, buf, (N/size), MPI_INT, &status);
/* // repeat the process again
MPI_Barrier(MPI_COMM_WORLD);
printf("2/ My rank is: %d\n", rank); */
MPI_File_close(&fp);
MPI_File_close(&fpwrite);
MPI_Finalize();
}
我不确定从哪里开始,我看到了几个带有光泽条纹的例子。如果可能的话,我想朝那个方向发展。其他选项包括 HDF5 和 T3PIO。
除了光泽条纹默认情况下对于 "parallel file system" 来说小得离谱的事实之外,您还太早担心光泽条纹。使用 lfs setstripe
增加您将写入和读取这些文件的目录的条带大小
您的第一个挑战是如何分解此 CSV 文件。典型的行是什么样的?如果行的长度可变,你会有点头疼。原因如下:
考虑一个包含 3 行和 3 个 MPI 进程的 CSV 文件。
- 一行是
aa,b,c
(8 个字节)。
- 行是
aaaaaaa,bbbbbbb,ccccccc
(24字节)。
- 第三行是
,,c
(4 个字节)。
(darnit, markdown,如何让这个列表从零开始?)
Rank 0 可以从文件的开头读取,但是Rank 1 和2 从哪里开始呢?如果简单地将总大小(8+24+4=36)除以3,那么分解就是
- 0 最终阅读
aa,b,c\naaaaaa
、
- 1 读
a,bbbbbbb,ccc
,
- 阅读
cccc\n,,c\n
非结构化文本输入的两种方式如下。一种选择是在事后或在生成文件时索引您的文件。该索引将存储每一行的起始偏移量。 Rank 0 读取偏移量然后广播给其他人。
第二个选项是按文件大小进行初始分解,然后修复拆分。在上面的简单示例中,等级 0 会将换行符之后的所有内容发送到等级 1。等级 1 将接收新数据并将其粘贴到其行的开头,并将其换行符之后的所有内容发送到等级 2。这非常繁琐且我不建议刚开始使用 MPI-IO 的人使用它。
HDF5 是一个不错的选择!与其尝试编写您自己的并行 CSV 解析器,不如让您的 CSV 创建者生成一个 HDF5 数据集。 HDF5 以及其他功能将保留我为您提到的索引,因此您可以设置 hyperslabs 并进行并行读写。
我有一个相当大的数据集,大约 1.41 亿行,格式为 .csv。我想在 C++ 中使用 MPI 命令来复制和操作一些列,但我是 C++ 和 MPI 的新手。
到目前为止我的代码是这样的
#include <stdio.h>
#include "mpi.h"
using namespace std;
int main(int argc, char **argv)
{
int i, rank, nprocs, size, offset, nints, bufsize, N=4;
MPI_File fp, fpwrite; // File pointer
MPI_Status status;
MPI_Offset filesize;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_File_get_size(fp, &filesize);
int buf[N];
for (i = 0; i<N; i++)
buf[i] = i;
offset = rank * (N/size)*sizeof(int);
MPI_File_open(MPI_COMM_WORLD, "new.csv", MPI_MODE_RDONLY, MPI_INFO_NULL, &fp);
MPI_File_open(MPI_COMM_WORLD, "Ntest.csv", MPI_MODE_CREATE|MPI_MODE_WRONLY, MPI_INFO_NULL, &fpwrite);
MPI_File_read(fp, buf, N, MPI_INT, &status);
// printf("\nrank: %d, buf[%d]: %d\n", rank, rank*bufsize, buf[0]);
printf("My rank is: %d\n", rank);
MPI_File_write_at(fpwrite, offset, buf, (N/size), MPI_INT, &status);
/* // repeat the process again
MPI_Barrier(MPI_COMM_WORLD);
printf("2/ My rank is: %d\n", rank); */
MPI_File_close(&fp);
MPI_File_close(&fpwrite);
MPI_Finalize();
}
我不确定从哪里开始,我看到了几个带有光泽条纹的例子。如果可能的话,我想朝那个方向发展。其他选项包括 HDF5 和 T3PIO。
除了光泽条纹默认情况下对于 "parallel file system" 来说小得离谱的事实之外,您还太早担心光泽条纹。使用 lfs setstripe
您的第一个挑战是如何分解此 CSV 文件。典型的行是什么样的?如果行的长度可变,你会有点头疼。原因如下:
考虑一个包含 3 行和 3 个 MPI 进程的 CSV 文件。
- 一行是
aa,b,c
(8 个字节)。 - 行是
aaaaaaa,bbbbbbb,ccccccc
(24字节)。 - 第三行是
,,c
(4 个字节)。
(darnit, markdown,如何让这个列表从零开始?)
Rank 0 可以从文件的开头读取,但是Rank 1 和2 从哪里开始呢?如果简单地将总大小(8+24+4=36)除以3,那么分解就是
- 0 最终阅读
aa,b,c\naaaaaa
、 - 1 读
a,bbbbbbb,ccc
, - 阅读
cccc\n,,c\n
非结构化文本输入的两种方式如下。一种选择是在事后或在生成文件时索引您的文件。该索引将存储每一行的起始偏移量。 Rank 0 读取偏移量然后广播给其他人。
第二个选项是按文件大小进行初始分解,然后修复拆分。在上面的简单示例中,等级 0 会将换行符之后的所有内容发送到等级 1。等级 1 将接收新数据并将其粘贴到其行的开头,并将其换行符之后的所有内容发送到等级 2。这非常繁琐且我不建议刚开始使用 MPI-IO 的人使用它。
HDF5 是一个不错的选择!与其尝试编写您自己的并行 CSV 解析器,不如让您的 CSV 创建者生成一个 HDF5 数据集。 HDF5 以及其他功能将保留我为您提到的索引,因此您可以设置 hyperslabs 并进行并行读写。