16

これがstackoverflowの誤用でないことを願っています。最近、Parallel Extensions に関するすばらしい質問をいくつか目にし、興味をそそられました。

私の質問: Parallel Extensions を使用していますか?

Stephen Toub と申します。Microsoft の Parallel Computing Platform チームに所属しています。Parallel Extensionsを担当するグループです。開発者が Parallel Extensions (例: Parallel.For、PLINQ、ConcurrentDictionary など) をどのように利用しているか、あなたが経験した肯定的な経験、否定的な経験、将来の機能要求などについて聞くことに常に興味があります。の上。
そのような情報を共有していただける場合は、この質問への回答としてここに送信するか、個人的にstoub at microsoft dot com.

私はあなたからの連絡をとても楽しみにしています。

前もって感謝します!

4

5 に答える 5

4

ネストされた呼び出しを行うために TPL を使用していParallel.ForEachます。これらの呼び出しから辞書にアクセスするため、 を使用する必要がありますConcurrentDictionary。それは素晴らしいことですが、いくつか問題があります。

  • 内部のデリゲートForEachはあまり仕事をしないので、並列処理はあまりできません。システムはほとんどの時間をスレッドの結合に費やしているようです。並行性が上がらない原因を突き止めて改善する方法があればいいですね。

  • 内部ForEach反復はConcurrentDictionaryインスタンスを超えているため、列挙子キャッシュを追加しなかった場合、システムは多くの時間を辞書の列挙子に費やすことになります。

  • 私のConcurrentDictionaryインスタンスの多くは実際にはセットですが、ないConcurrentSetので、ConcurrentDictionary.

  • ConcurrentDictionaryはオブジェクトの初期化構文をサポートしていないため、クラス メンバーにリテラルをvar dict = new ConcurrentDictionary<char, int> { { 'A', 65 } };割り当てることができないこともわかりません。ConcurrentDictionary

  • ConcurrentDictionaryでキーを検索し、高価な関数を呼び出して、値が存在しない場合に値を作成する必要がある場所がいくつかあります。キーが存在しない場合にのみ値を計算できるように、GetOrAddを取るのオーバーロードがあればいいのですが。addValueFactoryこれはシミュレートできます.AddOrUpdate(key, addValueFactory, (k, v) => v)が、ルックアップごとに追加のデリゲート呼び出しのオーバーヘッドが追加されます。

于 2010-12-13T07:55:07.443 に答える
1

私はまだそれを広く使用していませんが、その用途に耳を傾け、コードベースで使用する機会を探しています (残念ながら、私たちはまだ多くのプロジェクトで .NET-2.0 にバインドされています)。当面)。私が思いついた小さな宝石の 1 つは、ユニークな単語カウンターでした。これは私が思いつくことができる最も速くて簡潔な実装だと思います-誰かがそれを改善できるなら、それは素晴らしいことです:

private static readonly char[] delimiters = { ' ', '.', ',', ';', '\'', '-', ':', '!', '?', '(', ')', '<', '>', '=', '*', '/', '[', ']', '{', '}', '\\', '"', '\r', '\n' };
private static readonly Func<string, string> theWord = Word;
private static readonly Func<IGrouping<string, string>, KeyValuePair<string, int>> theNewWordCount = NewWordCount;
private static readonly Func<KeyValuePair<string, int>, int> theCount = Count;

private static void Main(string[] args)
{
    foreach (var wordCount in File.ReadAllText(args.Length > 0 ? args[0] : @"C:\DEV\CountUniqueWords\CountUniqueWords\Program.cs")
        .Split(delimiters, StringSplitOptions.RemoveEmptyEntries)
        .AsParallel()
        .GroupBy(theWord, StringComparer.OrdinalIgnoreCase)
        .Select(theNewWordCount)
        .OrderByDescending(theCount))
    {
        Console.WriteLine(
            "Word: \""
            + wordCount.Key
            + "\" Count: "
            + wordCount.Value);
    }

    Console.ReadLine();
}

private static string Word(string word)
{
    return word;
}

private static KeyValuePair<string, int> NewWordCount(IGrouping<string, string> wordCount)
{
    return new KeyValuePair<string, int>(
        wordCount.Key,
        wordCount.Count());
}

private static int Count(KeyValuePair<string, int> wordCount)
{
    return wordCount.Value;
}
于 2010-12-13T22:44:14.243 に答える
0

私は自分のプロジェクトMetaSharpでそれを使用しています。DSL 用の MSBuild ベースのコンパイル パイプラインがあり、1 つのステージ タイプは多対多ステージです。M:M ステージは .AsParallel.ForAll(...) を使用します。

スニペットは次のとおりです。

protected sealed override IEnumerable<IContext> Process()
{
    if (this.Input.Count() > 1)
    {
        this.Input
            .AsParallel<IContext>()
            .ForAll(this.Process);
    }
    else if (this.Input.Any())
    {
        this.Process(this.Input.Single());
    }

    return this.Input.ToArray();
}
于 2010-12-13T07:25:04.913 に答える
0

私たちはそれを広く使用していませんが、確かに重宝しています。

Parallel.Invoke()時間のかかるいくつかのステップを呼び出しにラップするだけで、実行時間の長いいくつかの単体テストの実行時間を元の時間の約 1/3 に短縮することができました。

また、並列ライブラリを使用してスレッド セーフをテストすることも大好きです。次のようなコードを使用して、Ninject でいくつかのスレッド化の問題をキャッチして報告しました。

var repositoryTypes = from a in CoreAssemblies
                    from t in a.GetTypes()
                    where t.Name.EndsWith("Repository")
                    select t;
repositoryTypes.ToList().AsParallel().ForAll(
    repositoryType => _kernel.Get(repositoryType));

実際の本番コードでは、いくつかの並列拡張機能を使用して、数分ごとに実行されるはずのいくつかの統合アクションを実行します。これらのアクションは、主に Web サービスからのデータのプルで構成されます。これは、Web 接続に固有の高いレイテンシーのため、並列処理の特別な利点を利用し、再起動する前にすべてのジョブの実行を終了できるようにします。

于 2010-12-13T23:07:32.463 に答える
0

1 億以上のアイテムを格納する ConcurrentDictionary を使用しています。私のアプリケーションは、その時点で約 8 GB のメモリを使用しています。次に、ConcurrentDictionary は、別の Add で拡張することを決定します。そして、メモリが不足すると、明らかにLOT(いくつかの内部プリマアルゴリズム)を増やしたいと考えています。これは、32 GB のメモリを搭載した x64 上にあります。

したがって、(同時)辞書の自動再成長/再ハッシュをブロックするブール値が必要です。次に、固定セットのバケットを使用して作成時に辞書を初期化します (これは固定容量とは異なります!)。また、バケツ内のアイテムが増えるにつれて、時間の経過とともに少し遅くなります。ただし、これにより、再ハッシュとメモリ不足が急速かつ不必要に発生するのを防ぐことができます。

于 2012-06-26T12:41:22.020 に答える