【问题标题】:stl hash_map slower than simple hash function?stl hash_map 比简单的散列函数慢?
【发布时间】:2011-10-08 02:48:01
【问题描述】:

我正在比较我编写的一个简单的哈希函数,它只是将它乘以一个素数 mod 另一个素数(表大小),结果 stl 慢了 100 倍。这是我写的测试方法:

stdext:: hash_map<string, int> hashDict;
for (int l = 0; l < size; ++l){
    hashDict[arr[l]] = l;
}
long int before3 = GetTickCount();
int c = 0;
while (c < size){
    hashDict[arr[c]];
    c++;
}
long int after3 = GetTickCount();
cout << "for stl class, the time is " << (after3 - before3) / 1000.0 << '\n';
cout << "the average is " << ((after3 - before3) / 1000.0 ) /long (size) << '\n';

字典的大小约为 200k 个元素,而我写的 hash 函数的表大小有 3m 个条目,所以可能与 stl 类的表大小非常小有关。有谁知道stl函数的tablesize和collision rates.etc?

【问题讨论】:

  • 这是我的哈希函数: unsigned hash(const char *s) { unsigned hashval; for (hashval = 0; *s != '\0'; s++) hashval = *s + PRIME * hashval;返回哈希值 % HASHSIZE; }
  • 这真的,真的需要更多信息来回答。你的简单哈希函数是什么,它有什么作用?另外,你在说什么hash_map 实现? STL 中没有一个(会有一个std::unordered_map&lt;&gt;)。最后,您没有对提供的代码中的哈希做任何事情;你确定你的版本在做什么?
  • 我只是从地图中检索元素,没有对它做任何事情。
  • @SuperString:你确定你真的在检索它们吗?如果你没有对它们做任何事情,你怎么知道你所做的一切都没有被优化?每当有一百倍的差异时,我怀疑编译器优化了一些东西。

标签: c++ hash c++builder


【解决方案1】:

VS2008 STL 实现对字符串使用以下哈希函数:

size_t _Val = 2166136261U;
while(_Begin != _End)
    _Val = 16777619U * _Val ^ (size_t)*_Begin++;

这并不比你的效率低​​,当然不会是 100 倍,而且我怀疑 Builder 版本有很大不同。区别要么在于测量(GetTickCount() 不是很精确),要么在于计算哈希值以外的操作。

我不了解 C++ Builder,但一些 STL 实现在调试版本中内置了许多额外的检查和断言。您是否尝试过分析优化的发布版本?

如果您发布一个最小但完整的示例,我们可以帮助您弄清楚发生了什么,但如果没有更多代码,真的没什么好说的。

【讨论】:

  • 我猜 216613626U 是表格大小而 16777619U 是质数?就 int 而言,这些数字是多少?您在哪里找到该代码?
  • 不,这些只是为了减少冲突而选择的常量,它们与特定的哈希表无关。就像在您的示例中一样,最终值被强制使用模数进入表格大小,但这与性能无关。代码在 &lt;xhash&gt; 标头中的函数 _Hash_value 中,但它是特定于实现的。
  • 那么stl hash_map类的表大小是多少?
  • 插入 200,000 个项目后有 262,145 个桶。它实际上可以是任何东西,但由于规范没有定义它,它由实现决定。
【解决方案2】:

将此作为答案发布:我认为您的价值观错误。您实际上并没有使用散列值,只是引用它们,因此编译器很可能会优化对您的散列表的访问,而不是 hash_map

除了在极端和罕见的情况下,您不会在仍然使用相同的算法的情况下以很大的积分因子击败专业的实现,就像您一样。您中彩票中大奖的可能性至少是中奖的 100 倍。

更改您的测试代码以使用这些值。将它们相加并打印出总和。这速度很快,并且会强制程序查找每个值。

【讨论】:

    【解决方案3】:

    我可以确认调试版本和发布版本之间可能存在巨大差异。 在我的示例中,我有使用 hash_map 和 list 的程序。 调试版本运行了 8 分钟。 发布版本在不到一秒的时间内运行。 这至少是 480 倍的时间差。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-11
      • 2010-11-16
      • 2011-01-17
      • 2011-08-19
      • 2014-04-22
      • 2011-05-23
      相关资源
      最近更新 更多