我正在尝试将一些带有字符串键的数据存储到字典中。数据非常大,例如数千万个字符串。因此,我决定开发一个并发版本以实现更快的执行。但是并发版本的性能非常糟糕。
我使用了两种策略:
1- 将输入分成两个块,并使用两个并发线程将每个块插入两个不同的字典中。
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;
}