我可以使用 MPI 中的 API 读取远程文件吗?
Can I read a remote file using APIs in MPI?
N台机器中的每台机器都有一个独占的部分数据作为二进制文件。 (文件只是固定大小数据类型的数组)
第i个proc能否读取第j个proc中数据文件的特定部分?;
(例如,第 i 个过程在第 j 个过程中从文件开头读取 4096 个字节。)
似乎MPI_File_*
操作需要将所有数据文件复制到每台机器的本地文件系统中才能具有此功能,除非我有分布式并行文件系统。
这可以通过单向 MPI 通信来模拟这一点。从这里开始,我将做一些假设(其中一些你已经在你的问题中确认):
- 您的文件是二进制文件,位于非共享文件系统(在我的示例中,每个进程或等级
r
将访问名为“/tmp/inputr
”的文件)
- 您在 Linux / Unix 集群上(我将在这里使用一些 POSIX 函数,我怀疑这些函数是否可以在 Windows 机器上运行)
- 您的文件太大,每个进程都无法将其读入缓冲区并随后公开(尽管如果文件很小,这可能是最简单的解决方案)
所以思路是每个进程以读模式打开自己的私有文件,内存映射,然后将mmap()
返回的内存地址暴露到一块MPI内存window。一旦完成,每个进程都可以使用这个 window 来访问它想要的各种文件的一部分。
这是它的样子:
#include <stdio.h>
#include <mpi.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main( int argc, char *argv[] ) {
MPI_Init( &argc, &argv );
int rank, size;
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
MPI_Comm_size( MPI_COMM_WORLD, &size );
// Open the local file
char fname[256];
snprintf( fname, 256, "/tmp/input%d", rank );
int fd = open( fname, O_RDONLY );
// And memory-map it
struct stat st;
fstat( fd, &st );
size_t len = st.st_size;
void *faddr = mmap( NULL, len, PROT_READ, MAP_PRIVATE, fd, 0 );
// Create a MPI memory window with the mapped files
MPI_Win win;
MPI_Win_create( faddr, len, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &win );
// Each process reads two integers from the next process' private file
int next = ( rank + 1 ) % size;
int values[2];
MPI_Win_lock( MPI_LOCK_EXCLUSIVE, next, 0, win );
MPI_Get( values, 2, MPI_INT, next, 0, 2, MPI_INT, win );
MPI_Win_unlock( next, win );
printf( "Process %d read values %d and %d from process %d's private file\n",
rank, values[0], values[1], next );
// Cleaning up
MPI_Win_free( &win );
munmap( faddr, len );
close( fd );
MPI_Finalize();
return 0;
}
为了测试,我创建了一些包含两个整数的文件:当前进程的等级和它加上 10000。我在 Linux 集群(有几个节点)和结果是:
~> mpicc -std=c99 mpimap.c -o mpimap
~> mpirun -n 10 ./mpimap
Process 0 read values 1 and 10001 from process 1's private file
Process 1 read values 2 and 10002 from process 2's private file
Process 2 read values 3 and 10003 from process 3's private file
Process 3 read values 4 and 10004 from process 4's private file
Process 5 read values 6 and 10006 from process 6's private file
Process 6 read values 7 and 10007 from process 7's private file
Process 9 read values 0 and 10000 from process 0's private file
Process 4 read values 5 and 10005 from process 5's private file
Process 7 read values 8 and 10008 from process 8's private file
Process 8 read values 9 and 10009 from process 9's private file
如您所见,它可以正常工作,既不需要提前读取私有文件,也不需要将文件放在共享文件系统上。
N台机器中的每台机器都有一个独占的部分数据作为二进制文件。 (文件只是固定大小数据类型的数组)
第i个proc能否读取第j个proc中数据文件的特定部分?; (例如,第 i 个过程在第 j 个过程中从文件开头读取 4096 个字节。)
似乎MPI_File_*
操作需要将所有数据文件复制到每台机器的本地文件系统中才能具有此功能,除非我有分布式并行文件系统。
这可以通过单向 MPI 通信来模拟这一点。从这里开始,我将做一些假设(其中一些你已经在你的问题中确认):
- 您的文件是二进制文件,位于非共享文件系统(在我的示例中,每个进程或等级
r
将访问名为“/tmp/inputr
”的文件) - 您在 Linux / Unix 集群上(我将在这里使用一些 POSIX 函数,我怀疑这些函数是否可以在 Windows 机器上运行)
- 您的文件太大,每个进程都无法将其读入缓冲区并随后公开(尽管如果文件很小,这可能是最简单的解决方案)
所以思路是每个进程以读模式打开自己的私有文件,内存映射,然后将mmap()
返回的内存地址暴露到一块MPI内存window。一旦完成,每个进程都可以使用这个 window 来访问它想要的各种文件的一部分。
这是它的样子:
#include <stdio.h>
#include <mpi.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main( int argc, char *argv[] ) {
MPI_Init( &argc, &argv );
int rank, size;
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
MPI_Comm_size( MPI_COMM_WORLD, &size );
// Open the local file
char fname[256];
snprintf( fname, 256, "/tmp/input%d", rank );
int fd = open( fname, O_RDONLY );
// And memory-map it
struct stat st;
fstat( fd, &st );
size_t len = st.st_size;
void *faddr = mmap( NULL, len, PROT_READ, MAP_PRIVATE, fd, 0 );
// Create a MPI memory window with the mapped files
MPI_Win win;
MPI_Win_create( faddr, len, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &win );
// Each process reads two integers from the next process' private file
int next = ( rank + 1 ) % size;
int values[2];
MPI_Win_lock( MPI_LOCK_EXCLUSIVE, next, 0, win );
MPI_Get( values, 2, MPI_INT, next, 0, 2, MPI_INT, win );
MPI_Win_unlock( next, win );
printf( "Process %d read values %d and %d from process %d's private file\n",
rank, values[0], values[1], next );
// Cleaning up
MPI_Win_free( &win );
munmap( faddr, len );
close( fd );
MPI_Finalize();
return 0;
}
为了测试,我创建了一些包含两个整数的文件:当前进程的等级和它加上 10000。我在 Linux 集群(有几个节点)和结果是:
~> mpicc -std=c99 mpimap.c -o mpimap
~> mpirun -n 10 ./mpimap
Process 0 read values 1 and 10001 from process 1's private file
Process 1 read values 2 and 10002 from process 2's private file
Process 2 read values 3 and 10003 from process 3's private file
Process 3 read values 4 and 10004 from process 4's private file
Process 5 read values 6 and 10006 from process 6's private file
Process 6 read values 7 and 10007 from process 7's private file
Process 9 read values 0 and 10000 from process 0's private file
Process 4 read values 5 and 10005 from process 5's private file
Process 7 read values 8 and 10008 from process 8's private file
Process 8 read values 9 and 10009 from process 9's private file
如您所见,它可以正常工作,既不需要提前读取私有文件,也不需要将文件放在共享文件系统上。