8.2. FEFS/LLIOへのファイル操作について

・書込み操作

FEFS/LLIOへのファイル書込み方法について、LLIOはFEFSのアクセス方法とは異なる部分があります。 そのため、1ファイルに対して書込むプロセス数や、IO方法に分けて説明します。

領域名

ファイル書込みプロセス数

1プロセス

複数プロセス

IO方法

MPI-IO使用しない

MPI-IO使用

MPI-IO使用しない

ノード内テンポラリ領域

1ファイルに対して1プロセスから書込む場合

MPI-IOを使用したファイル書込み方法 (*)

MPI-IOを使用しないファイル書込み方法 (*)

共有テンポラリ領域

1ファイルに対して1プロセスから書込む場合

MPI-IOを使用したファイル書込み方法

MPI-IOを使用しないファイル書込み方法

第2階層ストレージのキャッシュ領域

1ファイルに対して1プロセスから書込む場合

MPI-IOを使用したファイル書込み方法

MPI-IOを使用しないファイル書込み方法

第2階層ストレージ

1ファイルに対して1プロセスから書込む場合

MPI-IOを使用したファイル書込み方法

MPI-IOを使用しないファイル書込み方法

(* : ノード内に閉じた場合のみ使用可能)

・ファイル名変更操作

ファイル名変更操作については、ファイル名変更 で説明しています。

・ファイル削除操作

ファイル削除操作については、ファイル削除 で説明しています。

8.2.1. 1ファイルに対して1プロセスから書込む場合

1ファイルに対して1プロセスから書込みを行う場合は、FEFS/LLIOともに、write処理を実施します。

../_images/WriteFileSingleProcess_01.png

[1ファイルに対して1プロセスから 1 MB のデータを書込むコード例]

1int fd;
2fd = open("output.txt", O_WRONLY | O_CREAT, 0644);
3write(fd, data, 1000000);
4close(fd);

注意

コード例では省略していますが、open処理やwrite処理などのエラー対処は必ず行うようにしてください。

8.2.2. 1ファイルに対して複数プロセスから書込む場合

1ファイルに対して、複数プロセスから書込みを行う場合について、MPI-IOを用いた場合とwriteシステムコールを用いた場合で説明します。

../_images/WriteFileMultiProcess_01.png

8.2.2.1. MPI-IOを使用したファイル書込み方法

FEFS/LLIOともに、1ファイルに対して複数プロセスから書込む場合、MPI-IOを利活用できます。

[新規で作成した1ファイルに対して複数プロセスから 1 MB ずつデータを書込むコード例]

1MPI_File fh;
2MPI_File_open(MPI_COMM_WORLD, "output.txt", MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);
3MPI_Offset offset = RANK*1000000;
4MPI_File_write_at(fh, offset, data, 1000000, MPI_CHAR, MPI_STATUS_IGNORE);
5MPI_File_close(&fh);

注意

コード例では省略していますが、MPI_File_open処理やMPI_File_write_at処理などのエラー対処は必ず行うようにしてください。

ファイルを追記モード(MPI_MODE_APPEND)でopenした場合の例も記載します。

[追記モードでオープンした1ファイルに対して複数プロセスから 1 MB ずつデータを書込むコード例]

1MPI_File fh;
2MPI_File_open(MPI_COMM_WORLD, "output.txt", MPI_MODE_APPEND | MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);
3MPI_File_write(fh, data, 1000000, MPI_CHAR, MPI_STATUS_IGNORE);
4MPI_File_close(&fh);

注意

コード例では省略していますが、MPI_File_open処理やMPI_File_write処理などのエラー対処は必ず行うようにしてください。

8.2.2.2. MPI-IOを使用しないファイル書込み方法

MPI-IOを使用しないファイル書込み方法については、FEFS/LLIOで処理の実装方法が異なります。

・FEFS

FEFSでは、ファイルシステムの一貫性を保つため、lockを取得せずに、書き込み処理(write処理)を実行します。

[新規で作成した1ファイルに対して複数プロセスから 1 MB ずつデータを書込むコード例]

1 int fd;
2 fd = open("output.txt", O_WRONLY | O_CREAT, 0644);
3 lseek(fd, RANK*1000000, SEEK_SET);
4 write(fd, data, 1000000);
5 close(fd);

注意

コード例では省略していますが、open処理やwrite処理などのエラー対処は必ず行うようにしてください。

ファイルを追記モード(O_APPEND)でopenした場合の例も記載します。

[追記モードの1ファイルに対して複数プロセスから 1 MB ずつデータを書込むコード例]

1 int fd;
2 fd = open("output.txt", O_WRONLY | O_APPEND, 0644);
3 write(fd, data, 1000000);
4 close(fd);

注意

コード例では省略していますが、open処理やwrite処理などのエラー対処は必ず行うようにしてください。

・LLIO

LLIOの場合は、ファイルシステムにて一貫性の制御を行いません。 そのため、lockを取得してwrite処理を行う、または、Direct I/Oを用いてwrite処理を行います。

LLIOで使用可能はlockは、flock(2)、fcntl(2)です。

fcntl(2)でlockを取得してwrite処理を行うコード例を以下に記載します。

なお、第2階層ストレージキャッシュ領域で、第2階層ストレージへの書出しタイミングを制御したい場合は、第2階層ストレージへの書出しタイミングを参照してください。

[1ファイルに対して複数プロセスから 1 MB ずつデータを書込むコード例]

1 int fd;
2 fd = open("output.txt", O_WRONLY | O_CREAT, 0644);
3 lseek(fd, RANK*1000000, SEEK_SET);
4 struct flock lk0 = {.l_type=F_WRLCK, .l_whence=SEEK_SET, .l_start=RANK*1000000, .l_len=1000000};
5 fcntl(fd, F_SETLK, &lk0);
6 write(fd, data, 1000000);
7 struct flock lk1 = {.l_type=F_UNLCK, .l_whence=SEEK_SET, .l_start=RANK*1000000, .l_len=1000000};
8 fcntl(fd, F_SETLK, &lk1);
9 close(fd);

注意

コード例では省略していますが、open処理やwrite処理などのエラー対処は必ず行うようにしてください。

ファイルを追記モード(O_APPEND)でopenした場合の例も記載します。

[追記モードの1ファイルに対して複数プロセスから 1 MB ずつデータを書込むコード例]

1 int fd;
2 fd = open("output.txt", O_WRONLY | O_APPEND, 0644);
3 flock(fd, LOCK_EX)
4 write(fd, data, 1000000);
5 flock(fd, LOCK_UN);
6 close(fd);

注意

コード例では省略していますが、open処理やwrite処理などのエラー対処は必ず行うようにしてください。

Direct I/Oでのwrite処理のコード例を以下に記載します。 write時のアライメントや書込みサイズについては、計算ノードのページキャッシュのサイズ 64 KiB を考慮する必要があります。

[1ファイルに対して複数プロセスから 1 MB ずつデータを書込むコード例]

1 int size=1000000*100
2 posix_memalign( (void **)&data, 1000000, size);
3 int fd;
4 fd = open("output.txt", O_DIRECT | O_SYNC | O_WRONLY | O_CREAT, 0644);
5 lseek(fd, RANK*1000000, SEEK_SET);
6 write(fd, data, 1000000);
7 close(fd);

注意

コード例では省略していますが、open処理やwrite処理などのエラー対処は必ず行うようにしてください。

8.2.3. ファイル名変更

ファイル名を変更する場合は、FEFS/LLIOいずれの場合も、rename処理を実施します。

ただし、第2階層ストレージのキャッシュ領域または共有テンポラリ領域において、計算ノードAでファイルAを別名に変更した後に再作成した場合、計算ノードBでは、ファイルAのopen(2)が失敗することや、計算ノードAでファイルAを別名に変更したファイルがopen(2)されることがあります。

回避するには、以下の対処が必要です

  • 計算ノードBでファイルAをopen(2)する前に、ファイルAが存在している親ディレクトリに対してlsコマンドを実行する。

  • 計算ノードBでファイルAをopen(2)する前に、計算ノードAのファイルAの再作成後、60秒経過してからopen(2)を行う。

8.2.4. ファイル削除

ファイルを削除する場合は、FEFS/LLIOいずれの場合も、unlink処理を実施します。

ただし、第2階層ストレージのキャッシュ領域または共有テンポラリ領域において、計算ノードAでファイルAを削除した後に再作成した場合、計算ノードBでは、ファイルAのopen(2)が失敗することや、計算ノードAで削除したファイルがopen(2)されることがあります。

回避するには、以下の対処が必要です

  • 計算ノードBでファイルAをopen(2)する前に、ファイルAが存在している親ディレクトリに対してlsコマンドを実行する。

  • 計算ノードBでファイルAをopen(2)する前に、計算ノードAのファイルAの再作成後、60秒経過してからopen(2)を行う。