【发布时间】:2010-10-28 19:51:03
【问题描述】:
我正在编写一个 7 张牌扑克手评估器,作为我最喜欢的项目之一。在尝试优化其速度时(我喜欢这个挑战),我震惊地发现字典键查找的性能与数组索引查找相比非常慢。
例如,我运行了这个示例代码,它枚举了所有 52 个选择 7 = 133,784,560 个可能的 7 张牌:
var intDict = new Dictionary<int, int>();
var intList = new List<int>();
for (int i = 0; i < 100000; i ++)
{
intDict.Add(i, i);
intList.Add(i);
}
int result;
var sw = new Stopwatch();
sw.Start();
for (int card1 = 0; card1 < 46; card1++)
for (int card2 = card1 + 1; card2 < 47; card2++)
for (int card3 = card2 + 1; card3 < 48; card3++)
for (int card4 = card3 + 1; card4 < 49; card4++)
for (int card5 = card4 + 1; card5 < 50; card5++)
for (int card6 = card5 + 1; card6 < 51; card6++)
for (int card7 = card6 + 1; card7 < 52; card7++)
result = intDict[32131]; // perform C(52,7) dictionary key lookups
sw.Stop();
Console.WriteLine("time for dictionary lookups: {0} ms", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
for (int card1 = 0; card1 < 46; card1++)
for (int card2 = card1 + 1; card2 < 47; card2++)
for (int card3 = card2 + 1; card3 < 48; card3++)
for (int card4 = card3 + 1; card4 < 49; card4++)
for (int card5 = card4 + 1; card5 < 50; card5++)
for (int card6 = card5 + 1; card6 < 51; card6++)
for (int card7 = card6 + 1; card7 < 52; card7++)
result = intList[32131]; // perform C(52,7) array index lookups
sw.Stop();
Console.WriteLine("time for array index lookups: {0} ms", sw.ElapsedMilliseconds);
哪个输出:
time for dictionary lookups: 2532 ms
time for array index lookups: 313 ms
是否会出现这种行为(性能下降 8 倍)? IIRC,字典平均有 O(1) 查找,而数组有最坏情况 O(1) 查找,所以我确实希望数组查找更快,但不会这么快!
我目前将扑克手牌排名存储在字典中。我想如果这与字典查找一样快,我必须重新考虑我的方法并改用数组,尽管索引排名会有点棘手,我可能不得不问另一个问题。
【问题讨论】:
-
f 字典查找总是需要 1 小时才能完成单个项目,并且 总是 一个小时,即使是另一种类型的查找,它仍然是 O(1),例如数组查找,需要 1ms,也是 O(1)。您只能使用 big-O 表示法来比较复杂性,不要用它来实际测量代码的运行时性能特征。
-
我不认为复杂性不是正确的词,大 O 表示法告诉你它是如何随着项目数量而变化的。 O(1) 告诉您锁定是恒定的,即随着集合的增长,查找不会花费更长的时间。但是,查找可能具有非常高的复杂性,并且仍然像字典一样是 O(1),或者它们可能具有非常低的复杂性,并且像数组查找一样是 O(1)。
-
我很想知道您的方法与我的 OneJoker 库相比如何。它针对 5 张牌进行了优化,但可以做 7 张,我的查找表只有 1MB 左右,而你的可能接近 GB。
标签: c# .net performance poker