Microsoftの製品の1つであるMicrosoft
Roboticsには、Concurrent and Coordination Runtimeライブラリが含まれています。 ロボットは、音と画像(およびそれらだけではない)を処理する際に並列コンピューティングを整理するためのライブラリを本当に必要とします。 投稿では、次の式を使用して、このライブラリを使用して、マトリックスA(m×n要素)にベクトルB(1×n要素)を乗算する並列アルゴリズムを作成する方法を説明します。
。 ベクトルC(m×1要素)を計算するアルゴリズムは、ベクトルのi番目の要素の値が他の要素の値に依存しないため、簡単に並列化できます。 ソースから例を実行する前に、Microsoft Roboticsをインストールすることをお勧めします。
1. Microsoft Roboticsの簡単な紹介
Microsoft Roboticsには、いくつかのコンポーネントが含まれています。
- 並行および調整ランタイム(CCR)ライブラリ-並列および非同期で実行されるメソッドを使用してデータ処理を整理するように設計されています。 そのようなメソッド間の相互作用は、メッセージに基づいて編成されます。 メッセージングはポートに基づいています。
- 分散ソフトウェアサービス(DSS)-異なるコンピューターでデータ処理アルゴリズムを実行し、ロボットのさまざまなサブシステムの制御プロセスの非同期相互作用を整理できる環境。
- Visual Simulation Environment(VSE)-ロボットモデルの実験、ロボット制御アルゴリズムのテストを可能にする視覚化環境。
- Visual Programming Language(VPL)は、ロボット制御プログラムを開発するために設計された言語です。 この言語のプログラムは、データ処理を実行する一連のブロックと、それらの間の関係として表されます。
マイクロソフトロボティクスの主要概念:
- サービス-Microsoft Roboticsで開発されたアプリケーション。
- メッセージ-任意のデータ型のインスタンス。
- port-FIFOタイプ(先入れ先出し)のメッセージのキュー。メッセージは、受信者によってポートキューから削除されるまでポートに残ります。
ポート定義:
Port<int> p = new Port<int>();
ポートにメッセージを送信する:
p.Post(1);
- 受信者-メッセージを処理する構造。 この構造は以下を組み合わせます。
- メッセージが送信される1つ以上のポート。
- メッセージの処理に使用されるメソッド(このメソッドはタスクと呼ばれます)。
- 1人または別の受信者がアクティブになる状況を定義する論理条件。
受信者の説明:
Arbiter.Receive(<_>, <>, <_>); : Activate( Arbiter.Receive(false, intPort, delegate(int n) { Console.WriteLine(" : " + n.ToString()); } ) );
受信者に含まれるデリゲートは、メッセージがintPortポートに到着すると実行されます。
メッセージの受信者には、一時的なものと永続的なものの2種類があります(この例では、受信者は一時的なものです)。 メッセージ(または複数のメッセージ)を処理した一時的な受信者は、このポートのメッセージ受信者のリストから削除されます。
- タスクの起動プロセスはディスパッチャによって制御されます。 タスクのアクティベーション条件が満たされた後(アクティベーション条件の1つはポートによるメッセージの受信である場合があります)、ディスパッチャはタスクが実行されるスレッドプールからスレッドをタスクに割り当てます。
プールに2つのスレッドがあるマネージャーの説明:
Dispatcher d = new Dispatcher(2, "MyPool");
タスクが実行用に設定されているディスパッチャキューの説明:
DispatcherQueue dq = new DispatcherQueue("MyQueue", d);
2.サービスプロジェクトの作成
サービスプロジェクトは、Microsoft RoboticsタブのVisual Studioで作成されます(図1を参照)。
図 1.サービスプロジェクトの作成
プロジェクトを作成したら、サービスを構成する必要があります。プロジェクトの名前、名前空間、サービスが開発されている組織のドメイン、およびサービスが作成された年と月を指定します。 ドメインと日付は、一意のサービス識別子を作成するために使用されます(このプロジェクトでは、この識別子は直接必要ありません)。
図 2.サービスのセットアップ
サービスプロジェクトは、いくつかのファイルで構成されています。
- ParallelProcessing.cs-サービスのコア。
- ParallelProcessingTypes.manifest.xml-DSSがサービスをロードするために使用するマニフェスト。
- ParallelProcessingTypes.cs-サービスで使用されるタイプの説明が含まれています。
サービスをコンパイルすると、dllライブラリのセットとマニフェストが生成されます。 マニフェスト-開発されたサービスが対話するサービスへのリンクを含むXML形式のファイル。 サービスプロジェクトの設定は、サービスのコンパイル後に作成されたdllライブラリが\ binディレクトリにコピーされるように設定されます。
サービスはdsshostプログラムを使用して起動され、マニフェストとそれに指定されているすべてのサービスがロードされます。
3.サービス構造
サービスコードの構造には、DSSノード(dsshost.exe)がサービスを開始するときに呼び出されるStartメソッドが含まれています(したがって、通常、データを初期化するアクションはStartメソッドに配置されます)。
protected override void Start() { base.Start();
プロジェクトをコンパイルすると、3つのdllライブラリが生成されます。
- ParallelProcessing.Y2013.M02.dll-サービスプロジェクトに含まれるソースコードファイルに基づいて形成されたサービス実装ライブラリ。
- ParallelProcessing.Y2013.M02.proxy.dllライブラリを使用すると、サービスを他のサービスと併用できます。
- ParallelProcessing.Y2013.M02.transform.dllライブラリには、サービスの実装とプロキシライブラリの実装で定義されたタイプ間の対応の記述が含まれています。 このライブラリは、DSSランタイムを使用して自動的にロードされます。
作成したサービスは、Visual StudioのF5だけでなく、コマンドラインからも実行できます。 これを行うには、[スタート]メニューの[MRDS]で[DSSコマンドプロンプト]を選択します。 その結果、シェルウィンドウが起動し、ルートディレクトリと環境変数が設定されます。 開いたウィンドウで、次のコマンドを実行する必要があります。
dsshost /p:50000 /t:50001 /m:"< >"
4.推定リードタイム
計算の実行時間は、Stopwatchクラスを使用して決定されます。
Stopwatch sWatch = new Stopwatch(); sWatch.Start(); < > sWatch.Stop(); Console.WriteLine(sWatch.ElapsedMilliseconds.ToString());
5.コンピューティングの実装
5.1。 データ構造の宣言
マトリックスA、ベクトルBおよびC、サイズをグローバルに保存するための変数を決定します。
int[,] A; int[] B; int[] C; int m; int n;
TestFunction()メソッドは計算を開始します。 まず、この方法では、行列に逐次アルゴリズムを使用してベクトルを乗算し、次に並列計算を使用して同じ問題を解決します。 この方法を検討してください。
データ構造が初期化されます。
nc = 2;
行列AとベクトルBが生成されます。
Random r = new Random(); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) A[i, j] = r.Next(100); } for (int j = 0; j < n; j++) B[j] = r.Next(100);
5.2。 逐次乗算アルゴリズム
SequentialMulメソッドを検討してください。
Stopwatch sWatch = new Stopwatch(); sWatch.Start(); for (int i = 0; i < m; i++) { C[i] = 0; for (int j = 0; j < n; j++) C[i] += A[i, j] * B[j]; } sWatch.Stop(); Console.WriteLine(" = {0} .", sWatch.ElapsedMilliseconds.ToString());
5.3。 並列乗算アルゴリズム
並列処理は、計算メソッドの複数のコピーを実行することにより実行されます。 メソッドの各コピーは、ソースデータの特定の部分を処理します。 各メソッドのジョブを記述するために、InputDataクラスが使用されます。
public class InputData { public int start;
クラスの開始/停止フィールドには、計算メソッドのインスタンスを使用して計算されるベクトルCの開始/終了行番号が格納されます。
ParallelMulメソッドを検討してください。
次に、計算メソッドの各インスタンスの初期データが設定されます。
ディスパッチャは、2つのスレッドのプールで作成されます。
Dispatcher d = new Dispatcher(nc, "Test Pool"); DispatcherQueue dq = new DispatcherQueue("Test Queue", d);
Mul()メソッドの各インスタンスが計算の完了後にメッセージを送信するポートを記述します。
Port<int> p = new Port<int>();
Arbiter.Activateメソッドは、2つのタスク(Mulメソッドの2つのインスタンス)をディスパッチャーキューに入れます。
for (int i = 0; i < nc; i++) Arbiter.Activate(dq, new Task<InputData, Port<int>>(ClArr[i], p, Mul));
Arbiter.Activateメソッドの最初のパラメーターは、タスクの実行を制御するディスパッチャーキューです。2番目のパラメーターは、起動するタスクです。
Arbiter.MultipleItemReceiveメソッドを使用して、ポートpによる2つのメッセージの受信を処理するタスク(レシーバー)が起動されます。
Arbiter.Activate(Environment.TaskQueue, Arbiter.MultipleItemReceive(true, p, nc, delegate(int[] array) { Console.WriteLine(" "); }));
レシーバは、計算がいつ完了するかを判断するために使用されます。 2つのメッセージがポートpに到着した後にのみ機能します。 レシーバーで説明されているデリゲートには、乗算プロセスの完了後に実行する必要があるアクションを含めることができます。
Mul()メソッドは、行列の一部にベクトルを掛けます:
void Mul(InputData data, Port<int> resp) { Stopwatch sWatch = new Stopwatch(); sWatch.Start(); for (int i = data.start; i < data.stop; i++) { C[i] = 0; for (int j = 0; j < n; j++) C[i] += A[i, j] * B[j]; } sWatch.Stop(); Console.WriteLine(" № {0}: = {1} .", Thread.CurrentThread.ManagedThreadId, sWatch.ElapsedMilliseconds.ToString()); resp.Post(1); }
Mul()メソッドには2つのパラメーターがあります。
1)メソッドの入力に渡されるパラメーターを定義する配列要素の値を格納するインデックス。
2)計算の完了後に整数が送信される完了ポート。
計算が完了すると、Mulメソッドは整数値をポートpに送信します(送信される値は任意です)。
計算結果を図に示します。 3。
図 3.計算の結果
ソースへのリンク