4

こんにちは、ご覧いただきありがとうございます。

バックグラウンド

多くの時間を必要とする計算タスク、または並列計算があります。

具体的には、約 50 個の画像のリストをループ処理し、それらを Base64 でエンコードしてから、新たにエンコードされた各アイテムと、約 2000 個の Base64 文字列でエンコードされた画像を含む XML ファイル内の値との間のレーベンシュタイン距離を計算して、最小の Lev を持つ XML ファイル。ベンチマーク文字列からの距離。

通常のforeachループは機能しますが、遅すぎるため、Core i7 マルチコア プロセッサを利用するために PLINQ を使用することにしました。

Parallel.ForEach(candidates, item => findImage(total,currentWinner,benchmark,item));

タスクは見事に開始され、高速で実行されますが、「メモリ不足」の例外が発生します。

C#、.NET 4、Forms アプリを使用しています。

質問

使用可能なメモリが不足しないように PLINQ コードを微調整するにはどうすればよいですか?

アップデート/サンプルコード

PLINQ を開始するために呼び出されるメソッドを次に示しforeachます。

private void btnGo_Click(object sender, EventArgs e)
{
    XDocument doc = XDocument.Load(@"C:\Foo.xml");
    var imagesNode = doc.Element("images").Elements("image"); //Each "image" node contains a Base64 encoded string.
    string benchmark = tbData.Text; //A Base64 encoded string.
    IEnumerable<XElement> candidates = imagesNode;

    currentWinner = 1000000; //Set the "Current" low score to a million and bubble lower scores into it's place iteratively.
    
    Parallel.ForEach(candidates, i => {
        dist = Levenshtein(benchmark, i.Element("score").Value);
        if (dist < currentWinner)
        {
            currentWinner = dist;
            path = i.Element("path").Value;
        }
    });
}

. . .そして、ここにレーベンシュタイン距離法があります:

public static int Levenshtein(string s, string t)    {
            int n = s.Length;
            int m = t.Length;
            var d = new int[n + 1, m + 1];

            // Step 1
            if (n == 0)
            {
                return m;
            }

            if (m == 0)
            {
                return n;
            }

            // Step 2
            for (int i = 0; i <= n; d[i, 0] = i++)
            {
            }

            for (int j = 0; j <= m; d[0, j] = j++)
            {
            }

            // Step 3
            for (int i = 1; i <= n; i++)
            {
                //Step 4
                for (int j = 1; j <= m; j++)
                {
                // Step 5
                int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;

                // Step 6
                d[i, j] = Math.Min(
                    Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
                    d[i - 1, j - 1] + cost);
                }
            }
            // Step 7
            return d[n, m];
            }

前もって感謝します!

4

1 に答える 1

6

アップデート

今日、さまざまな状況でこのエラーが再び発生しました。私は、メモリ需要の高いデスクトップ アプリに取り組んでいました。使用可能なすべてのメモリにアクセスできるように、プロジェクトを 64 ビット アーキテクチャに設定していることを確認してください。私のプロジェクトはデフォルトで x86 に設定されていたため、メモリ不足の例外が発生し続けました。もちろん、これは展開に 64 ビット プロセッサを当てにできる場合にのみ機能します。

更新終了

これに少し苦労した後、オペレーターのエラーのようです:

進行状況ラベルを更新するために並列スレッドから UI スレッドへの呼び出しを行っていましたが、スレッドセーフな方法では実行していませんでした。

さらに、デバッガーなしでアプリを実行していたため、コードが並列スレッドから UI スレッドを更新しようとするたびに例外がキャッチされず、オーバーフローが発生しました。

PLINQ の専門家でなくても、このような間抜けな臭いコード エラーを起こさない限り、低レベルの割り当てはすべて PLINQ で処理されると思います。

これが他の誰かに役立つことを願っています。

于 2012-01-09T03:30:10.993 に答える