8.2. FEFS/LLIOへのファイル操作について¶
・書込み操作
FEFS/LLIOへのファイル書込み方法について、LLIOはFEFSのアクセス方法とは異なる部分があります。 そのため、1ファイルに対して書込むプロセス数や、IO方法に分けて説明します。
領域名
ファイル書込みプロセス数
1プロセス
複数プロセス
IO方法
MPI-IO使用しない
MPI-IO使用
MPI-IO使用しない
ノード内テンポラリ領域
共有テンポラリ領域
第2階層ストレージのキャッシュ領域
第2階層ストレージ
(* : ノード内に閉じた場合のみ使用可能)
・ファイル名変更操作
ファイル名変更操作については、ファイル名変更 で説明しています。
・ファイル削除操作
ファイル削除操作については、ファイル削除 で説明しています。
8.2.1. 1ファイルに対して1プロセスから書込む場合¶
1ファイルに対して1プロセスから書込みを行う場合は、FEFS/LLIOともに、write処理を実施します。

[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システムコールを用いた場合で説明します。

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)を行う。