2

並列計算に関するいくつかのことを理解するのに再び苦労しています。私が取り組んでいるコードには、拡張するクラスがありますlist<list<double>>。このクラス内で、 の値の平均を返すメソッドを作成していlist<list<double>>ます。このメソッドは非公開です。

public class myClass : list<list<double>>
{
    //properties and stuff
    private double average()
    {
        //method body
    }
}

この方法には 2 つのバージョンがあり、どちらも機能しています。最初のバージョンはシリアルです:

private double average()
{
    double avg = 0;
    for (int i = 0; i < this.Count; i++)
    {
        for (int j = 0; j < this[0].Count; j++)
        {
            avg += this[i][j];
        }
    }
    avg = avg / (this.Count*this[0].Count);
    return avg;
}

2 番目のバージョンは並列です。

private double average()
{
    double avg = 0;
    double[] cumsum = new double[this.Count];
    Parallel.For(0, this.Count, i =>
        {
            cumsum[i] = 0;
            for (int j = 0; j < this[0].Count; j++)
            {
                cumsum[i] += this[i][j];
            }
        });
    avg = cumsum.Sum() / ((this.Count * this[0].Count));
    return avg;
}

学習課題として、より複雑な並列スレッドを使用して物事を混乱させようとしました。私のアイデアは、行を合計する中間配列なしでやり遂げることでした。具体的には、これは私の試みでした(動作しません):

private double average()
{
    double avg = 0;
    Parallel.For<double>(0, this.Count, () => 0, (i, loop, sub) =>
        {
            for (int j = 0; j < this[0].Count; j++)
            {
                sub += this[i][j];
            }
            return sub;
        },
        (x) => 
            {
                double tot = avg;
                Interlocked.CompareExchange(ref avg, tot+sub, tot);
            });
    return avg / ((this.Count * this[0].Count));
}

このスニペットには (少なくとも) 2 つの誤りがあります。それが私に与える最初のエラーは次のsub += this[i][j];とおりです:

'System.Collections.Generic.List>.this[int]' に最適なオーバーロードされたメソッドの一致には、いくつかの無効な引数があります

i と j の両方が int 型であるため、ここではこのエラーを理解できません。

次に、さらにエラーが発生しますInterlocked.CompareExchange(ref avg, tot+sub, tot);(この方法がどのように機能するかを本当に理解していないため、予想されます):

名前 'sub' は現在のコンテキストに存在しません

誰かが最後のスニペットの正しい形式を教えてくれますか? および/またはこのことを明確にするための資料はありますか? http://msdn.microsoft.com/en-us/library/dd460703.aspxから読みましたが、物事を明確にするのに役立ちませんでした。

4

2 に答える 2

2

個人的には、次を使用します。

double sum = yourListOfList.AsParallel().SelectMany(list => list).Average();

メソッドを修正するには、ローカルの最終ラムダでループ状態をプロパティ使用する必要があります。(現在はまったく使用していませんx。)

double sum = 0;
var syncObj = new object();
Parallel.For<double>(0, this.Count, () => 0, (i, loop, sub) =>
    {
        var innerList = this[i];
        for (int j = 0; j < innerList.Count; j++)
        {
            sub += innerList[j];
        }
        return sub;
    },
    (x) => 
        {
            lock(syncObj)
               sum += x;
        });
return sum / ((this.Count * this[0].Count));

あなたのバージョン (および私の「修正」) には多くの欠点があることに注意してください。各サブリストは と同じ長さthis[0]であると想定していますが、これはタイプによって保証または提案されていません。

于 2013-08-13T18:32:40.100 に答える