5.9 並列計算
解析の並列度(使用するスレッド数)を設定し、(1) 行列ソルバ内部の並列、(2) 荷重ケース単位の並列、(3) 非線形解析の要素ループ並列の 3 種類で解析を高速化します。既定は自動(使用可能な全コア)で速度を優先します。ですが、単一スレッド(設定値 1)を指定すると、同一入力に対するビット一致の再現性(決定性)を保証します。
並列度の設定
並列度はプロセス全体の設定(squid_n_math::parallelism)で、GUI では右パネル「① 準備計算」の「計算条件」で指定します:
| 設定値 | 意味 |
|---|---|
| 0(既定) | 自動。使用可能な全コアを使う |
| 1 | 単一スレッド。同一入力でビット一致の再現性を保証する |
| n(2 以上) | スレッド数を n に固定する |
ソルバ内部並列では浮動小数点加算の順序が変わり得るため(加算の非結合性)、結果は単一スレッド実行とビット単位では一致しません。ただし各荷重ケースの計算はケース間で状態を共有せず独立に行われるため、値としての差は丸め誤差程度であり、工学的判断に影響しません(検証は単一スレッド解との値一致で行います)。ビット一致の再現が必要な場合(V&V・回帰試験・成果の完全再現)は 1 を指定します。なお、後述の要素ループ並列(非線形解析)はこの例外で、並列でも単一スレッド実行とビット単位で完全に一致します。
並列化の 3 種類
- ソルバ内部の並列(inner): 疎 Cholesky / LU の分解・求解(5.1 の線形代数ソルバ)を複数スレッドで実行することで、解析準備(全体剛性の組立と分解)を高速化します。
- 荷重ケース単位の並列(outer): 分解済みの剛性行列を共有し、複数の荷重ケースを並列に解きます(
Analysis::linear_static_batch)。一貫計算では多数の荷重ケース(長期・地震 X/Y など)を同一の剛性で解くため、実務ワークフローでもっとも効果が大きくなります。GUI の「一括解析」は、この経路で全荷重ケースを解いたうえで、荷重組合せをその結果の線形和として組み立てます(5.2.1 荷重組合せの応答)。荷重組合せ自体は求解を伴わないため、並列化の対象は荷重ケースの数になります。 - 非線形解析の要素ループ並列: 非線形時刻歴応答解析・増分解析(プッシュオーバー)の反復計算で繰り返される要素単位の処理(要素状態の更新、接線剛性の組立、内力の集計)を、要素ごとに並列実行します。各要素の計算は要素間で状態を共有せず独立で、結果の集約は常に要素番号順に行うため、浮動小数点の加算順序が単一スレッド実行と完全に同一になり、結果はビット単位で一致します(ソルバ内部並列と異なり、並列化しても決定性が失われません)。効果は要素数が多いモデルほど大きく、要素数が少ない小規模モデルではスレッド化のオーバーヘッドが計算短縮を上回ることがあります。
分解(factorize)は 1 回だけ行い、各ケースは前進・後退代入と内力復元のみを行います(5.1・5.2 参照)。ケースごとの計算は荷重ベクトル組立 → 求解 → 変位展開 → 部材断面力復元の全工程が独立で、結果の格納順は入力順に固定されます。
スレッドの自動配分
ケース並列(outer)とソルバ内部並列(inner)を同時に全開にすると、合計要求スレッド数(outer × inner)がコア数を超えて奪い合いが起き、かえって遅くなります。このためバッチ解析では、総枠(設定スレッド数、自動なら全コア数)を両者へ自動配分します:
\[ \text{outer} = \min(\text{ケース数},\ \text{総枠}), \qquad \text{inner} = \max!\left(1,\ \left\lfloor \text{総枠} / \text{outer} \right\rfloor\right) \]
- ケース数 ≥ コア数: inner = 1(全コアをケース並列に使う)
- ケース数 < コア数: 余りコアをソルバ内部並列へ回す
- 1 ケースのみ: ケース並列なし。設定どおりのソルバ内部並列で解く
バッチ終了後は設定値の並列度へ戻ります。
配分例(8 コアマシン、並列スレッド数 0=自動のとき)
| 状況 | ケース並列 | ソルバ内部並列 | 動き |
|---|---|---|---|
| 荷重ケース 16 件の一括解析 | 8 | 1 | 全コアをケース並列に使う。16 件は 8 スレッドへ順次割り当てられる |
| 荷重ケース 4 件の一括解析 | 4 | 2 | 4 ケースを同時に解き、各ケースの求解に 2 スレッドを使う |
| 荷重ケース 3 件の一括解析 | 3 | 2 | ⌊8/3⌋=2。合計 6 スレッドの要求に留め、コア数の超過(奪い合い)を避ける |
| 1 ケースのみ・単体実行 | – | 8 | ケース並列なし。ソルバ内部並列が全コアを使う |
| 解析準備(剛性組立+分解)・固有値・時刻歴 | – | 8 | 一括解析以外の処理はソルバ内部並列が全コアを使う |
端数が出るケース(例: 3 件)では、切り捨て配分により一部のコアを割り当てませんが、超過配分してスレッドを奪い合うより速くなります(実測は後述のベンチマーク参照)。
速度の目安
同梱のベンチマーク(cargo run -p squid-n-solver --example parallel_bench --release)で、実行環境での効果を確認できます。参考値(4 コア、約 34,000 自由度・部材 15,480 の立体ラーメン):
| 処理 | 単一スレッド比 |
|---|---|
| 荷重ケース 16 件の一括解析 | 約 3.5〜4 倍 |
| 荷重ケース 2 件の一括解析 | 約 1.8〜1.9 倍 |
| 解析準備(剛性組立+分解) | 約 1.3 倍 |
ケース数がコア数以上のとき並列化効率がもっとも高く、コア数までほぼ線形にスケールします。剛性組立は現状単一スレッドのため、解析準備の向上率は分解の並列化分に留まります。
実装: squid_n_math::parallelism(並列度設定・線形代数ライブラリへの反映・スレッドプール)、squid_n_solver::statics::analysis::Analysis::{linear_static_batch, linear_static_with_combinations}(ケース並列とスレッド配分)、squid_n_solver::dynamic::timehistory/squid_n_solver::nonlinear::pushover(非線形解析の要素ループ並列)、GUI は解析タブ(squid-n-app)が担当します。