同じ、異なるを繰り返し解く


12

MATLABを使用して、が時間とともに変化するすべてのタイムステップでを解く問題を解決しています。現在、MATLABを使用してこれを実現しています:Ax=bbmldivide

x = A\b

必要なだけ多くの事前計算を行う柔軟性があるので、より高速で正確な方法があるかどうか疑問に思っていmldivideます。ここで通常行われることは何ですか?皆さんありがとう!


1
の構造に関する特定の知識はありますか?たとえば、対称ですか?正の確定?三重対角線?直交?A
ドミニク

行列は密な正方行列です。A
疑い

3
に関する他の知識がない場合は、以下の回答で説明されている分解が最善の策です。L UALU
ドミニク

回答:


14

あなたができる最も明白なことは、事前計算することです

[L,U] = lu(A) 〜O(n ^ 3)

次に計算するだけです

x = U \ (L \ b) 〜O(2 n ^ 2)

これにより、コストが大幅に削減され、高速化されます。精度は同じです。


1
ドキュメントから、Lは必ずしも下三角ではないことに注意してください。この答えは直接解くよりも速いでしょうが、L \ bコマンドがLを正しい順序で解くのに十分なほどスマートであることを確認するように注意しますドキュメント内)。
ゴドリックシーア

そうですね、Lは下三角行列と置換行列の積です。しかし、私はそれがやらなければならないすべてがでの後方置換であるということを認識しないならば、のろわれますL\b。私はこの正確な行が高性能コードで私が専門家と考える人々によって使用されているのを見たので。
Milind R

8
mldivideは、置換された三角行列を認識し、そのようなシステムを解く際に正しいます。ただし、私の実験では、サイズ2000から2000から10000から10000の行列の場合、これによりソリューションプロセスが10倍ほど遅くなるようです。したがって、[L 、U、P] = lu(P)。On2
ブライアンボーチャーズ

1
また、行列がスパースの場合、スパース性を利用してシステムを解く必要があります。これを実行する最も簡単な方法は、ことを確認することです LU分解を計算する前に、A =スパース(A)を使用して、スパース形式で保存されています。LU分解中の塗りつぶしを減らすために、Aの行を並べ替えることもできます。A
ブライアンボーチャーズ

3
@BrianBorcher私の知る限り、順列を追跡する最善の方法[L,U,p] = lu(A,'vector'); x = U\(L\b(p));lu docsの例3を参照してください。
ステファノM

5

このトピックに関する科学コンピューティングコースでは、広範なコンピューターラボを実施しました。そこで行われた「小さな」計算では、Matlabのバックスラッシュ演算子は、コードを可能な限り最適化し、すべての行列を事前に調整した後でも(たとえば、スパース行列の逆Cuthill McKee順序付けを使用した場合) 。

ラボの手順の 1つを確認できます。質問への回答は、4ページで(まもなく)カバーされます。

このトピックに関する良い本は、例えばチェイニーによって書かれています。


4

仮定あるのn × nは行列、あなたが解決しなければならAをxは、私は = bの私は= 1 ... メートルを。場合は、mがある十分に大きい、その後何も間違っているではありAn×n Axi=bii=1mm

V = inv(A);
...
x = V*b;

フロップは for およびO n 2 forです。したがって、mの損益分岐値を決定するには、いくつかの実験が必要です。O(n3)inv(A)O(n2)V*bm

>> n = 5000;
>> A = randn(n,n);
>> x = randn(n,1);
>> b = A*x;
>> rcond(A)
ans =
   1.3837e-06
>> tic, xm = A\b; toc
Elapsed time is 1.907102 seconds.
>> tic, [L,U] = lu(A); toc
Elapsed time is 1.818247 seconds.
>> tic, xl = U\(L\b); toc
Elapsed time is 0.399051 seconds.
>> tic, [L,U,p] = lu(A,'vector'); toc
Elapsed time is 1.581756 seconds.
>> tic, xp = U\(L\b(p)); toc
Elapsed time is 0.060203 seconds.
>> tic, V=inv(A); toc
Elapsed time is 7.614582 seconds.
>> tic, xv = V*b; toc     
Elapsed time is 0.011499 seconds.
>> [norm(xm-x), norm(xp-x), norm(xl-x), norm(xv-x)] ./ norm(x)
ans =
   1.0e-11 *
    0.1912    0.1912    0.1912    0.6183

この些細な例では、m > 125の場合、事前計算がL Uの前方および後方解よりも優れています。A1LUm>125

いくつかのメモ

安定性とエラー分析については、この異なる回答、特にVictorLiuの回答に対するコメントを参照してください。

提案されたタイミングはまったく「科学的」ではありませんが、関連するLAPACKおよびBLASサブルーチンを呼び出すことでCまたはFortranで実装された場合、Milind R の回答で提案されたアプローチは完全に理にかなっていることを示すことを意味するさえは、MATLABに有効mn

5のほぼ一定のUNIX負荷平均で、12コアコンピューターでMatlab R2011bを使用してタイミングを実行しました。tic, toc3つのプローブのベストタイム。


実際、行列ベクトル乗算では、三角ソルバーよりもはるかに多くの並列処理が利用できるため、計算が何らかの方法で並列に実行される場合(マルチコア/ GPU /など)に、これはさらに明白になるはずです。
アロンアーマディア

@AronAhmadia私は同意します:操作数のみに基づく損益分岐点の推定は、シリアル実装に対してのみ意味があります。
ステファノM

1
A行列がスパースの場合は物事が大幅に異なることに注意してください。通常、逆行列は非常に密で、LUファクターは一般に適度にスパースで、LUの方向に物事が高速に戻ります。
ブライアンボーチャーズ

1
A

1
inv(A)Ax=bbBA\B

2

この質問を見てください、答えmldivideは非常に賢いことを示しており、Matlabが解決に使用するものを見る方法についての提案も提供しA\bます。これにより、最適化オプションに関するヒントが得られる場合があります。


0

バックスラッシュの使用は、とほぼ同等inv(A)*Bですが、自由にコーディングする場合は、後者の方がより直感的です。これらはほぼ同じです(計算の実行方法が異なる)が、明確にするためにMatlabのドキュメントを確認する必要があります。

あなたの質問に答えるために、バックスラッシュは一般に問題ありませんが、質量行列の特性に依存します。


1
数学的には、inv(A)* bは\と同じですが、数値的には、実際に逆行列を形成すると効率と精度が低下します。線形代数の学習に取り組んでいる場合、これは受け入れられるかもしれませんが、逆行列を形成するためには非常に正当な理由が必要だと主張します。
ゴドリックシーア

しかし、なぜinv(A)それだけで計算するよりも高価なのですA\bか?
ドミニク

7
@Godric:inv(A)* bの精度が低いという「神話」について議論した最近の論文があります:ArXivに。通常、実際の逆数を計算する理由があると言っているのではなく、単に言っています。
ビクター

3
@Dominique:三角解法は行列ベクトル乗算よりもはるかに並列化が難しく、洗練された事前条件付き反復法はサブドメインで直接法を使用することがよくあります。並列性を改善するために、いくつかの適度なサイズの密な三角行列の逆行列を明示的に形成すると便利な場合がよくあります。
ジャックポールソン

@VictorLiu:記事をありがとう。私は自分の正確さの声明を修正しました(少なくともinv(A)のスマートな実装の場合)。
ゴドリックシーア
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.