お世話になっております。
C#で既存プログラムの実装の高速化をしたいと思っています。
以下のような木構造があり、それぞれのノードにはDictionaryでenum型に応じたkeyとdouble型のスコア値をvalueとして格納しています。
それぞれのエッジのスコアをrootから順に合計し、それぞれの枝について一番深いノードのスコア(図の赤色のスコア)を合計して出したいと思っています。
実際はもっと複雑なアルゴリズムでノード間のスコアを決めるためにノードごとに共有される変数が必要になり、単純にそれぞれのスコアタイプごとにツリー構造をインスタンス化して並列化するという解決策は難しいということを前提としてください。
エッジのスコアとrootのスコアの初期値は既知でノードごとのスコアの累積和が未知の時に木構造の最も深いノードのスコアの累積和を求めるプログラムを書くと以下のようになりました。
一度通ったノードであれば再計算する必要がないのでそれぞれのノードにそのノード時点でのスコアの累積和を(Ditcionary<int,double> score)にキャッシュさせ、一度計算した経路については親の累積スコアを使いまわすことで計算を効率化するようにしています。
C#
1class Program{ 2 static double ROOT_SCORE=0.1; 3} 4class Node{ 5 6 7 public Ditcionary<int,double> score; 8 private Dictionary<int,double> _edgeScore; 9 //constructor 省略 10 double edgeScore(int stype){ 11 return _edgeScore[stype]; 12 } 13 public double calcScore(int stype,bool recalc=false) 14 { 15 if (score.ContainsKey(type)&&!recalc) { 16 return score[stype]; 17 } 18 if (parent != null) 19 { 20 score[stype] = edgeScore(stype) 21 score[stype] += parent.calcScore(score,recalc); 22 return score[stype]; 23 } 24 else 25 { 26 return ROOT_SCORE; 27 } 28 } 29 30} 31 32//末端のNodeは取得できる 33//List<Node> deepestNodes = new List<Node>{deepNode1,deepNode2}; 34//deepestNodes.Select(node=>types.Select(type=>node.calcScore(type)));
このとき、この処理をtypeごと,末端nodeごとに並列化したいのですがこれらの並列化にはDictionary scoreの排他制御。をしなければいけないと思うのですが。Dictionaryごとロックする方法は出てくるのですが、Dictionaryインスタンスすべてをロックするのは効率が悪いのでDictionaryのkeyの参照先のオブジェクトの書き込みの排他制御を行いたいと思っています。(つまり、要約するとstypeごとの実行はほかのstypeと競合しないので並列化,stypeの中ではノードの分岐点までは並列化,分岐点では排他制御がしたいということです。)このようなことは可能なのでしょうか?よろしくお願いいたします。
必要があれば、子から親までのパスはノードを作るときに作成できます。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/01/25 06:06
2017/01/25 06:22
退会済みユーザー
2017/01/25 09:55 編集