Determinant and Inverse return wrong values when called from more than one thread
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 35/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 停滞
- 技術スタック
- csharp
- 領域
- performance
調査の方向性
まず SquareMatrixFactory<T, TWrapper>.GetMatrix と ExpressionCompiler<T, TWrapper>.storage から始め、コールドキャッシュを含めて、報告された行列式/逆行列の失敗を Parallel.For で再現します。完了条件は、並行行列演算が、コレクション例外や共有バッファーの破損なしに、逐次実行で検証された値を返すことです。
索引モデルが issue の本文から書いたものです。
説明
Two process-wide statics are read and written with no synchronisation, so matrix operations called from more than one thread return wrong numbers. Nothing throws, nothing is malformed, and no result looks suspicious.
I found this from the other side: AngouriMath uses GenTensor for its symbolic matrices, and a determinant computed on a background thread was coming back numerically wrong. AngouriMath's issue is #1219.
1. The scratch-matrix pool
SquareMatrixFactory<T, TWrapper>.GetMatrix hands every caller the same GenTensor for a given size, and the caller then writes into it — Inversion.GetCofactorMatrix(t, temp, ...) fills the matrix it is given. Two threads taking a determinant or an inverse of the same size get the same buffer and overwrite each other's minors between the write and the read.
Sixty 5×5 int matrices, each computed once sequentially for truth and then rebuilt and recomputed under Parallel.For:
DeterminantLaplace 53 of 60 disagree
Adjoint 60 of 60 disagree
Around 10 ms, every run. This is not a rare interleaving, it is the normal case.
DeterminantGaussianSafeDivision is unaffected — it works on its own copy and never asks the pool for anything.
The lock inside GetMatrix does not help and is itself incomplete: the list is indexed after the lock is released, so a concurrent Add can reallocate the backing array underneath the reader.
2. The compiled-operation cache
ExpressionCompiler<T, TWrapper>.storage is a plain Dictionary, written by whichever thread first asks for a given (operation, rank, parallel). Dictionary<,> is documented as safe for concurrent readers only while nobody is writing.
Reached cold from several threads it fails with the runtime's own diagnostic:
System.InvalidOperationException: Operations that change non-concurrent collections must
have exclusive access. A concurrent update was performed on this collection and corrupted
its state. The collection's state is no longer correct.
...
The given key '(Subtraction, 1, False)' was not present in the dictionary.
Worth noting that this one hides easily. My first test computed its expected values sequentially and only then went parallel, which populated every key before the threads started — the cache holds a handful of entries, so a warm-up makes the defect invisible and the test passes against the broken code.
Fix
I have opened a PR. Both are small: [ThreadStatic] for the pool, since a scratch buffer has nothing to share between threads, and ConcurrentDictionary for the cache. The Laplace determinant comes out about 5% faster, because the pool is now taken once at the top of the recursion instead of re-checked and re-indexed at every one of its n! nodes.
- 主要言語
- C#
- スター
- 52
- フォーク
- 6
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
ASC-Community/GenericTensor のほかの issue
-
good first issue
難易度 4/5 3〜5日 初心者へのやさしさ 25/100
-
proposal
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
ASC-Community/GenericTensor#36 · コメント 1 件 ·
-
Opinions wanted proposal
難易度 5/5 1週間以上 初心者へのやさしさ 25/100
ASC-Community/GenericTensor#31 · コメント 2 件 ·
-
Will this package support MKL or OpenBlas as backend to accelerate matrix inverse computing speedオープン
難易度 5/5 1週間以上 初心者へのやさしさ 25/100
ASC-Community/GenericTensor#30 · コメント 1 件 ·
-
難易度 5/5 1週間以上 初心者へのやさしさ 20/100
ASC-Community/GenericTensor#29 · コメント 1 件 ·
ASC-Community/GenericTensor の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
PCL-Community/PCL-CE#3658 ·
メンテナーはふだん 1 日以内に返信
-
Deploy & Patch-issues opprettes ikke: create-pnd-issues.yml har feilet hver uke siden 2025-09-08オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
Altinn/altinn-auth#4359 ·
メンテナーはふだん 1 日以内に返信
-
アプリ: チャット 優先: 中 提案
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
yksr-melt/Meltype#243 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
type/automation type/tech-debt
難易度 1/5 1時間未満 初心者へのやさしさ 72/100
メンテナーはふだん 1 日以内に返信
-
no-stack-trace
難易度 2/5 1〜3時間 初心者へのやさしさ 83/100
メンテナーはふだん 1 日以内に返信