問題の説明
Python/numpy でモンテカルロ粒子シミュレーター (ブラウン運動と光子放出) を作成中。シミュレーション出力 (>>10GB) をファイルに保存し、2 番目のステップでデータを処理する必要があります。Windows と Linux の両方との互換性は重要です。
粒子の数 ( n_particles
) は 10 ~ 100 です。時間ステップ数 ( time_size
) は ~10^9 です。
シミュレーションには 3 つのステップがあります (以下のコードはオールイン RAM バージョン用です)。
rate 配列をシミュレート (および保存) し
emission
ます (ほぼ 0 の要素を多数含む):- 形状 (
n_particles
xtime_size
)、float32、サイズ80GB
- 形状 (
配列を計算
counts
します (以前に計算されたレートを持つポアソン過程からのランダム値):形状 (
n_particles
xtime_size
)、uint8、サイズ20GBcounts = np.random.poisson(lam=emission).astype(np.uint8)
カウントのタイムスタンプ (またはインデックス) を見つけます。カウントはほとんどの場合 0 であるため、タイムスタンプ配列は RAM に収まります。
# Loop across the particles timestamps = [np.nonzero(c) for c in counts]
ステップ 1 を 1 回実行してから、ステップ 2 ~ 3 を何度も (~100 回) 繰り返します。将来的には、計算する前に前処理emission
(適用cumsum
または他の関数)が必要になるかもしれませんcounts
。
質問
私は動作中のメモリ内実装を持っており、(はるかに) 長いシミュレーションに拡張できるコア外バージョンを実装するための最良のアプローチは何かを理解しようとしています。
存在してほしいもの
配列をファイルに保存する必要があり、シミュレーションに 1 つのファイルを使用したいと考えています。また、シミュレーション パラメーター (スカラー) のディクショナリを格納および呼び出す "簡単な" 方法も必要です。
理想的には、チャンクを事前に割り当てて埋めることができる、ファイルでバックアップされた numpy 配列が必要です。次に、numpy 配列メソッド ( max
、cumsum
、...) を透過的に動作させchunksize
、各反復でロードする配列の量を指定するキーワードのみを必要とします。
さらに良いことに、キャッシュと RAM の間ではなく、RAM とハード ドライブの間で動作するNumexprが必要です。
実用的なオプションは何ですか
最初のオプションとして、pyTables の実験を開始しましたが、その複雑さと抽象化に満足していません (numpy とは大きく異なります)。さらに、私の現在のソリューション(以下を参照)は醜く、あまり効率的ではありません。
だから私が答えを求める私の選択肢は
必要な機能を備えた numpy 配列を実装する (どのように?)
よりスマートな方法でpytableを使用する(異なるデータ構造/メソッド)
h5py、blaze、pandas などの別のライブラリを使用します (これまで試したことはありません)。
暫定的な解決策 (pyTables)
シミュレーション パラメーターを'/parameters'
グループに保存します。各パラメーターは numpy 配列スカラーに変換されます。詳細なソリューションですが、機能します。
データをチャンクで生成し、新しいチャンクごとに追加する必要があるため (ただし、最終的なサイズはわかっています)、emission
拡張可能な配列 ( ) として保存します。EArray
貯蓄counts
はもっと問題です。pytable 配列のように保存すると、「counts >= 2」のようなクエリを実行するのが難しくなります。したがって、カウントを複数のテーブル (パーティクルごとに 1 つ) [UGLY] として保存し、.get_where_list('counts >= 2')
. これがスペース効率に優れているかどうかはわかりません。単一の配列を使用する代わりにこれらすべてのテーブルを生成すると、HDF5 ファイルが大幅に破壊されます。さらに、奇妙なことに、これらのテーブルを作成するには、カスタム dtype を作成する必要があります (標準の numpy dtype の場合でも):
dt = np.dtype([('counts', 'u1')])
for ip in xrange(n_particles):
name = "particle_%d" % ip
data_file.create_table(
group, name, description=dt, chunkshape=chunksize,
expectedrows=time_size,
title='Binned timetrace of emitted ph (bin = t_step)'
' - particle_%d' % particle)
各粒子カウント「テーブル」には異なる名前 ( name = "particle_%d" % ip
) があり、簡単に反復できるようにそれらを Python リストに入れる必要があります。
編集: この質問の結果は、PyBroMoと呼ばれるブラウン運動シミュレーターです。