パラレルHDF 5とh 5 py

5679 ワード

前編ではHDF 5とh 5 pyの基本操作について簡単に説明したが、以下ではmpi 4 pyとh 5 pyを用いた並列分散型HDF 5ファイル操作について説明する.
mpi 4 pyを使用した一般的なパラレルファイル操作については、前述したように、パラレルHDF 5ファイルの関連操作は、一般的なパラレルファイル操作と同じか、類似の制約条件を満たすことが多い.しかしmpi 4 pyとh 5 pyを用いてパラレルHDF 5ファイルの操作を行うと、HDF 5ファイルの多くのパラレル操作の詳細は使用者にとって透明であり、ユーザの関心を必要としないため、パラレルHDF 5ファイルの操作の難易度が大幅に低減される.
h 5 pyによるパラレルHDF 5操作
HDF 5ファイルを並列に開く/作成するには、前述の方法を使用し、パラメータdriverを「mpio」およびcommを有効な通信サブオブジェクトとして設定することができる.
ファイルの開く/作成は集合操作であり、通信サブオブジェクト上のすべてのプロセスが同時に参加する必要があります.
ファイルを開くと、groupの作成、datasetの作成/読み取り、attributeの設定/読み取りなど、並列のファイル読み書き操作を実行できますが、コレクション操作と独立操作の2つの操作方法に注意し、区別する必要があります.ファイル構造およびファイルメタデータの変更に関する操作は、groupの作成、datasetの作成、attributeの設定など、集合操作(すなわち、通信サブオブジェクト上のすべてのプロセスが同時に参加しなければならない)である必要がありますが、各プロセスは、既存のdatasetに独立してデータを書き込むか、データを読み出すことができます.
バージョン1.8.9+から、HDF 5は原子操作モードをサポートし、原子モードはファイル操作の一貫性をより厳格に保証することができる.パラレルファイル操作の原子性と一貫性については,前述したファイルデータへのアクセス方法で説明した.h 5 pyで原子操作モードを開くには、ファイル操作ハンドルのatomicプロパティをTrueに設定します.
ルーチン
以下、h 5 pyを用いた並列HDF 5動作の使用例を示す.
# parallel_h5.py

"""
Demonstrates how to use parallel HDF5 with h5py.

Run this with 4 processes like:
$ mpiexec -n 4 python h5py_demo.py
"""

import os
import numpy as np
import h5py
from mpi4py import MPI


comm = MPI.COMM_WORLD
rank = comm.rank
size = comm.size

N = 10
# N = 2**29

file_name = 'test.hdf5'
# create a new HDF5 file collectively
f = h5py.File(file_name, driver='mpio', comm=comm)
# use atomic mode
f.atomic = True
# create a new group collectively
f.create_group('grp')
# create a empty dataset in group "/grp" collectively
f.create_dataset('grp/dset', shape=(size, N), dtype=np.int32)
# set an attribute of the dataset grp/dset collectively
f['grp/dset'].attrs['a'] = 1

data = np.arange(N, dtype=np.int32)
# write data to dataset grp/dset
f['grp/dset'][rank, :] = data
# rank 0 changes a slice of the dataset individually
if rank == 0:
    f['grp/dset'][1, :] += data
# synchronize here
comm.Barrier()
# rank 2 reads the changed slice
if rank == 2:
    print f['grp/dset'][1, :]
# read the attrs
if rank == 1:
    print f['grp/dset'].attrs['a']

# close file collectively
f.close()

# remove the created file
if rank == 0:
    os.remove(file_name)

実行結果は次のとおりです.
$ mpiexec -n 4 python parallel_h5.py
[ 0  2  4  6  8 10 12 14 16 18]
1

2 GB dataset制限
上記のルーチンは正常に動作していますが、Nを229以上に設定すると、各プロセスがファイルに書き込むデータ≧2 GBになります.実行結果は次のようになります.
$ mpiexec -n 4 python parallel_h5.py
Traceback (most recent call last):
File "parallel_h5.py", line 37, in 
    f['grp/dset'][rank, :] = data
File "/opt/python-2.7.5-mkl/lib/python2.7/site-packages/h5py/_hl/dataset.py", line 551, in __setitem__
    self.id.write(mspace, fspace, val, mtype)
File "h5d.pyx", line 217, in h5py.h5d.DatasetID.write (h5py/h5d.c:3225)
Traceback (most recent call last):
File "parallel_h5.py", line 37, in 
    f['grp/dset'][rank, :] = data
File "/opt/python-2.7.5-mkl/lib/python2.7/site-packages/h5py/_hl/dataset.py", line 551, in __setitem__
Traceback (most recent call last):
File "parallel_h5.py", line 37, in 
    self.id.write(mspace, fspace, val, mtype)
File "h5d.pyx", line 217, in h5py.h5d.DatasetID.write (h5py/h5d.c:3225)
    f['grp/dset'][rank, :] = data
File "/opt/python-2.7.5-mkl/lib/python2.7/site-packages/h5py/_hl/dataset.py", line 551, in __setitem__
    self.id.write(mspace, fspace, val, mtype)
File "h5d.pyx", line 217, in h5py.h5d.DatasetID.write (h5py/h5d.c:3225)
Traceback (most recent call last):
File "parallel_h5.py", line 37, in 
    f['grp/dset'][rank, :] = data
File "/opt/python-2.7.5-mkl/lib/python2.7/site-packages/h5py/_hl/dataset.py", line 551, in __setitem__
    self.id.write(mspace, fspace, val, mtype)
File "h5d.pyx", line 217, in h5py.h5d.DatasetID.write (h5py/h5d.c:3225)
File "_proxy.pyx", line 120, in h5py._proxy.dset_rw (h5py/_proxy.c:1793)
File "_proxy.pyx", line 120, in h5py._proxy.dset_rw (h5py/_proxy.c:1793)
File "_proxy.pyx", line 120, in h5py._proxy.dset_rw (h5py/_proxy.c:1793)
File "_proxy.pyx", line 120, in h5py._proxy.dset_rw (h5py/_proxy.c:1793)
File "_proxy.pyx", line 93, in h5py._proxy.H5PY_H5Dwrite (h5py/_proxy.c:1603)
File "_proxy.pyx", line 93, in h5py._proxy.H5PY_H5Dwrite (h5py/_proxy.c:1603)
File "_proxy.pyx", line 93, in h5py._proxy.H5PY_H5Dwrite (h5py/_proxy.c:1603)
File "_proxy.pyx", line 93, in h5py._proxy.H5PY_H5Dwrite (h5py/_proxy.c:1603)
IOError: can't prepare for writing data (Dataset: Write failed)
IOError: can't prepare for writing data (Dataset: Write failed)
IOError: can't prepare for writing data (Dataset: Write failed)
IOError: can't prepare for writing data (Dataset: Write failed)

プログラムの実行中にエラーが発生しました.これは、パラレルHDF 5ファイルの読み書き操作が単一プロセスで一度に操作されるデータ量が2 GBのサイズ制限があり、2 GBを超えるとエラーになるためです.実はこれはパラレルHDF 5自体の問題ではなく、h 5 pyの問題ではなく、MPIの問題であり、より正確にはMPIのパラレルI/O操作ツールROMIOの問題である(ROMPIOは現在ほとんどのMPIが実現しているデフォルトまたは唯一のパラレルI/Oツールである).この制限は、ROMIOのI/O操作のほとんどが1回で許容されるデータ量が2 GB以内に制限されているため、将来ROMIOが改善されない限り存在し続ける.したがって,並列HDF 5操作を行う際には,1回の読み書きのデータ量が2 GBを超えないように注意すべきであり,2 GBを超えるデータを読み書きする場合はnumpy配列スライスのような機能を用いて複数回操作することができる.
以上、mpi 4 pyとh 5 pyによるパラレル分散型HDF 5ファイルの操作について説明しました.次の記事では、caputのmemh 5モジュールについて説明します.ここでは、HDF 5ファイルと同様のデータ構造をメモリで操作し、ディスク内のHDF 5ファイルへのデータ構造のマッピングを提供する強力なツールをいくつか提供します.もちろんこれらの操作は並列に分散的に行うことができる.