多くの場合、応用数学モデルおよびコンピューターモデルでは、線形代数方程式(
SLAE )のシステムを解く必要があります。 原則として、実際には、このようなSLAEのマトリックスはスパースです。 たとえば、スパース行列は、微分方程式を解くための有限差分法または有限要素法を使用したモデルで見つかります。 大規模な技術ネットワーク(ガス供給およびガス分配システム、下水道および熱供給システム、電気ネットワークおよびコンピューターネットワークなど)で材料および情報の流れをモデリングすると、非常に疎な行列が発生します。 テクノロジーネットワークに共通しているのは、モデルをグラフ形式で表示することです。この形式では、入射行列はほとんど常に非常にまばらです。
この記事では、ManagedCudaライブラリとnVidia CUDA 7.0の使用により、謙虚な使用人が、任意の構成の大規模なガス供給システムで非定常ガス流量を計算するためのコンピューターモデルの効率を大幅に向上させた方法について説明します。 ただし、プレゼンテーションは特定の主題分野に関係なく行われます。
問題の声明
SLAEを解決する古典的な問題は次のように考えられます。
Ax = bここで、サイズ
n x
nの行列
A 、
xはサイズ
nの未知数のベクトル、
bはサイズ
nの既知の自由項のベクトルです。
この記事の著者は、ガス供給システムでの非定常ガス流のモデリングと最適化のための専用のソフトウェアとコンピューターの複合体(
PVC )を開発しています。 私が解く問題では、
Aは特定の非線形方程式系の対角優位をもつ正定ヤコビアンです。
Aは 、ガス供給システムグラフの入射マトリックスと他のマトリックスのマトリックス変換の結果として取得されます。 私の実際の計算で
は 、
Aは通常6〜10%満杯で、残りはゼロです。 そのサイズは特定のガス供給システムのサイズに依存し、
nは10から1000まで変化します。
私たちのPVCは、C#の.NET 4.0で開発されています。 計算モジュールとすべての数学もC#で開発されています。 最初に、SLAEを解決するために、スパースマトリックステクノロジを使用しない独自のライブラリを作成しました。 SLAEを解決するために、
LU分解法を使用しました。 とりあえず、すべてが私に合っていましたが、非定常ガス流レジームを最適化するタスクを扱うようになるまでは、動的プログラミング法を使用して制御パラメーター値の多数の列挙を実行し、それに応じてSLAEを何度も解決する必要がありました。 標準のVisual Studioプロファイラーは、プログラムの実行中に、SLAEソリューションがコストの約40%を占めることを示しました。
その瞬間、何かを変える時だと気づいたのです。
Math.Net Numerics Math Library
.Netの既存の数学ライブラリを分析した後、Math.Net Numericsライブラリを停止することにしました。
ここでそれに慣れることができ
ます 。
主な機能に興味がありました:
- 実装された技術のスパース行列とベクトル。
- 必要なすべてのベクトル行列演算が組み込まれています。
- 組み込みのソルバーがあります。
- 直感的なAPI。
以下は、Math.Net Numericsを使用したSLAEソリューションの例のリストです。
SparseMatrix matrix = new SparseMatrix(n); double[] rightSide = new double[n];
ご覧のとおり、すべてが非常にエレガントに見えますが、ほとんどすぐに失望してしまいました。組み込みのMath.Net Numericsソルバーは、私のものよりもはるかに遅く動作しました。 これはまったく私には向いていませんでしたが、ライブラリに実装されているベクトル行列演算に対する主張はそれほど重要ではありません。 そのため、Math.Net Numericsを完全に放棄したわけではなく、ベクトルと行列を扱うコードを残しました。
しかし、その後、グラフィックプロセッサを使用して地下流体力学の問題を解決した大学院生の非常に成功した経験を思い出しました。 2 GBのメモリとCUDAテクノロジーをサポートするnVidia GeeForce GT 540Mグラフィックスカードを搭載したラップトップを自由に使用できます。 この技術を実際に試してみることにしましたが、今は後悔していません。
ManagedCudaライブラリ
このサイトにはCUDAテクノロジーに関する大量の資料がありますので、好奇心reader盛な読者は簡単に見つけることができます。 私は自分自身のために設定されたタスクをどのように解決したかについて詳しく説明します。
cuSPARSEライブラリに興味があり
ました 。 最初に彼女に会ったとき、私は問題に遭遇しました:
- ライブラリを使用した直接作業は、C / C ++を介してのみ可能です。 もちろん、私が本当に書きたくなかった高品質のラッパーを使用すれば、問題は解決します。 検索結果に基づいて、 Cudafyと呼ばれる.NetのCUDAラッパーが見つかりました 。
- cuSPARCEを使用すると、三角行列でSLAEを解くことができますが、私の場合、行列は解きません。 ただし、cuSPARSEには、それらの三角形形式( LU分解法、コレスキー分解)につながる行列分解法が含まれています。 ただし、Cudafy APIには適切なメソッドがなかったため、Cudafyを放棄する必要がありました。
検索を続けた後、CUDA APIの高レベルラッパーである
ManagedCudaライブラリを発見しました。 すべての機能をリストするわけではありません-それらは公式Webサイトで見つけることができますが、Math.Net NumericsとManagedCudaを使用して、SLAUをエレガントかつ効果的に解決する方法について詳しく説明します。
アイデアは、Math.Net NumericsのSparseMatrixを使用して、
CSR形式でスパース行列を形成および保存し、cuSPARSEおよびManagedCudaが受信することです。 以下は、対応するプログラムのリストです。
SparseMatrix matrix = new SparseMatrix(n); double[] rightSide = new double[n]; // //... var storage = matrix.Storage as SparseCompressedRowMatrixStorage<double>; // // CSR var nonZeroValues = storage.EnumerateNonZero().ToArray(); // double[] x = new double[matrix.RowCount]; // CudaSolveSparse sp = new CudaSolveSparse(); // ManagedCuda CudaSparseMatrixDescriptor matrixDescriptor = new CudaSparseMatrixDescriptor(); // double tolerance = 0.00001; // . sp.CsrlsvluHost(matrix.RowCount, nonZeroValues.Length, matrixDescriptor, nonZeroValues, storage.RowPointers, storage.ColumnIndices, rightSide, tolerance, 0, x); // LU
計算実験:さまざまな技術を使用したSLAEの解決に費やされた時間の分析
読者に無理のないテキストとプログラムのリストを退屈させないために、さまざまな技術を使用して50から500までのSLAU次元を計算した結果を考慮します。
- 記事の著者によって書かれた自家製ソルバー。 それをMani.Netと呼びましょう。
- Math.Net Numericsライブラリの標準ソルバー。
- ManagedCudaライブラリのLU分解メソッド。
マトリックス
Aはランダムに10%満たされます。
この図は、SLAEを解決するためにMath.Net Numericsを放棄しなければならなかった理由を明確に示しています。
マトリックス次元が500の場合、自分のソルバー(Mani.Net)には1170ミリ秒、Math.Net Numerics-12968ミリ秒、ManagedCuda-70ミリ秒かかりました。
おわりに
すべてのマシンがCUDAをサポートするnVidia GPUを搭載しているわけではないと言って、コメントにコメントを期待する必要があります。 確かにそうです。 したがって、このアプリケーションは、独自のSLAUソリューションライブラリとManagedCudaの2つのコンパイル構成用に構成されています。
Mani.Netに関しては、これは自分のライブラリの広告ではないことに注意してください。 どこでもそれを見つけることは不可能であり、私は誰にもそれを渡すことはありません。 いいえ、私は貪欲ではありません。 私はコードを恥じています。
記事を読んでくれてありがとう! コメントにあるあなたの意見やコメントを喜んでお知らせします。