文字列キーを持つデータを辞書に保存しようとしています。データは非常に大きく、たとえば数千万の文字列です。そのため、より高速な実行を実現するために、並行バージョンを開発することにしました。ただし、並行バージョンのパフォーマンスは非常に悪いです。
私は 2 つの戦略を使用しました:
1- 入力を 2 つのチャンクに分割し、2 つの同時スレッドを使用して各チャンクを 2 つの異なる辞書に挿入します。
2- Parallel.ForEach 呼び出しを使用して、データ全体を ConcurrentDictionary に挿入します。
しかし残念なことに、どちらの戦略のパフォーマンスも有望ではありません。最初の戦略は約20 ~ 30%優れていますが、タスク間でデータが共有されていないため、十分ではありません。また、同時収集は約100% 遅くなります。
今、私は何が問題なのか疑問に思っています??????? これは、この問題で並列速度が向上する可能性がないことを意味しますか? 誰かが私を助けることができれば、私は感謝します:)
以下にサンプルコードを添付しました。
私のデュアルコア AMD Turion システムでのサンプル結果は (ミリ秒単位):
初期化: 542
シリアル: 294
並列: 234
同時 Dic: 666
static void Main(string[] args)
{
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
watch.Start();
Random r = new Random();
int count=1000000;
string[] list = new string[count];
for (int i = 0; i < count; i++)
{
list[i] = r.Next(10000).ToString();
}
watch.Stop();
Console.WriteLine("Initialization: "+watch.ElapsedMilliseconds);
watch.Reset();
watch.Start();
Dictionary<string, byte> dic1 = new Dictionary<string, byte>();
Dictionary<string, byte> dic2 = new Dictionary<string, byte>();
foreach (var s in list)
dic1[s] = 0;
watch.Stop();
Console.WriteLine("Serial: " + watch.ElapsedMilliseconds);
watch.Reset();
watch.Start();
dic1.Clear();
Task t1 = new Task(
() =>
{
for (int i = 0; i < list.Length / 2; i++)
dic1[list[i]] = 1;
}
);
Task t2 = new Task(
() =>
{
for (int i = list.Length / 2; i < list.Length; i++)
dic2[list[i]] = 1;
}
);
t1.Start();
t2.Start();
Task.WaitAll(t1, t2);
watch.Stop();
Console.WriteLine("Parallel: " + watch.ElapsedMilliseconds);
watch.Reset();
watch.Start();
ConcurrentDictionary<string, byte> dicp = new ConcurrentDictionary<string, byte>();
Parallel.ForEach(list, s =>
{
dicp.AddOrUpdate(s, 1, (k, v) => v);
}
);
watch.Stop();
Console.WriteLine("Concurrent Dic: " + watch.ElapsedMilliseconds);
watch.Reset();
watch.Start();
Console.ReadKey();
return;
}