C# 中的哈希表比 C++ 更快?
Posted
技术标签:
【中文标题】C# 中的哈希表比 C++ 更快?【英文标题】:Hash table faster in C# than C++? 【发布时间】:2010-12-26 05:59:07 【问题描述】:这是我一直在调查的一个好奇心。在我一直运行的测试中,与 STL unordered_map 相比,.NET Dictionary 类的执行速度快得离谱,我不知道为什么。
(在我的机器上为 0.5 秒与 4 秒) (.NET 3.5 SP1 与 Visual Studio 2008 Express SP1 的 STL)
另一方面,如果我用 C# 和 C++ 实现自己的哈希表,C++ 版本的速度大约是 C# 版本的两倍,这很好,因为它强化了我的常识,即本机机器代码有时更快。 (见。我说“有时”。)我在两种语言中都是同一个人,我想知道微软的 C# 编码器有什么技巧可以玩微软的 C++ 编码器不能?我很难想象编译器如何自己发挥这些技巧,并经历优化应该看起来是任意函数调用的麻烦。
这是一个简单的测试,存储和检索整数。
C#:
const int total = (1 << 20);
int sum = 0;
Dictionary<int, int> dict = new Dictionary<int, int>();
for(int i = 0; i < total; i++)
dict.Add(i, i * 7);
for(int j = 0; j < (1 << 3); j++)
int i = total;
while(i > 0)
i--;
sum += dict[i];
Console.WriteLine(sum);
C++:
const int total = (1 << 20);
int sum = 0;
std::tr1::unordered_map<int, int> dict;
for(int i = 0; i < total; i++)
dict.insert(pair<int, int>(i, i * 7));
for(int j = 0; j < (1 << 3); j++)
int i = total;
while(i > 0)
i--;
std::tr1::unordered_map<int, int>::const_iterator found =
dict.find(i);
sum += found->second;
cout << sum << endl;
【问题讨论】:
C++ 版本的类型是否像 Dictionary您正在衡量显式内存管理的成本。更多统计数据可用here. 这是relevant too. 和Chris Sells' attempt 为 CLR 添加确定性终结是值得注意的。
【讨论】:
【参考方案2】:在代码级别会有一些差异:无序映射采用一对这一事实会强制构造此类对象,而 C# 在 Add 中传递两个参数可能会更快。
另外一点是哈希表本身的实现:哈希函数的实现,或者说处理冲突的方式,会导致不同的性能模式。
加上对齐和缓存、某些算法的 JIT 友好性,以及比较两种不同语言的两种不同实现变得非常困难,您唯一可以比较的是手头的特定任务。尝试使用更少或更多元素,或者尝试随机访问元素而不是按顺序访问元素,您可能会看到截然不同的结果。
【讨论】:
【参考方案3】:这两个版本是不等价的,您在 C++ while 循环的每次传递中都构造了一个迭代器。这会占用 CPU 时间并抛出您的结果。
【讨论】:
同意 - 尝试替换“dict.insert(pairFindEntry
方法的语法便利。它没有速度优势。
@Ben,在我的 STL 版本中没有任何地方有 FindEntry 方法。此外,下标运算符和 find 方法的实现也完全不同,这使我相信它们的执行方式可能与另一种完全不同。我不确定应该是哪个,但是适当的性能测试应该很容易证明这一点
@Ben,如果您指的是 C# 下标运算符,那么很抱歉我选错了。但是,OP 应该尝试在两种实现中编写正确的代码,而不是将好的 C# 代码与平均 C++ 实现进行比较以上是关于C# 中的哈希表比 C++ 更快?的主要内容,如果未能解决你的问题,请参考以下文章