【问题标题】:C++ map::find & map::at performance differenceC++ map::find 和 map::at 性能差异
【发布时间】:2018-10-23 19:49:31
【问题描述】:

我正在对一些练习和一个特定程序进行评分,尽管算法似乎正确,但它太慢了(我的意思是 慢)。该程序正在使用map::at(在 C++11 中引入)访问地图。只需将at 替换为find(并修复语法),同样的程序会非常快(与原始版本相比)。

查看 cplusplus.com 两种方法都声称具有相同的复杂性,但我不明白为什么其中一种会有所不同(除了 API 原因、不引发异常等)。

然后我看到关于数据竞争的部分中的描述有所不同。但我并不完全理解其中的含义。我的假设是否 map::at 是线程安全的(而 map::find 不是)并因此导致一些运行时惩罚正确吗?

http://www.cplusplus.com/reference/map/map/at/

http://www.cplusplus.com/reference/map/map/find/

编辑

两者都在一个称为 10.000.000 次的循环中。没有优化标志。只需g++ foo.cpp。这是差异(arrayX 是向量,m 是地图)

<               auto t = m.find(array1.at(i));
<               auto t2 = t->second.find(array2.at(i));
<               y = t->second.size();
<               cout << array.at(i) << "[" << t2->second << " of " << y << "]" << endl;
---
>               auto t = m.at(array1.at(i));
>               x = t.at(array2.at(i));
>               y = m.at(array1.at(i)).size();
>               cout << array.at(i) << "[" << x << " of " << y << "]" << endl;

【问题讨论】:

  • 除了 API 原因,不抛出异常等” - 这会影响性能。特别是如果它是算法的关键部分。线程安全版本也慢了一点
  • 我在两个版本中都没有出现任何异常。所以没有“活动”异常处理发生,没有堆栈展开等。
  • 您误解了异常的处理。考虑std::vectors operator[]at 函数。他们俩的速度都是O(1)。它们都使您可以访问nth 元素。但是,如果您提供了不正确的索引,operator[] 的行为是未定义的。可能它会给你一个垃圾参考。 at,另一方面,每次调用它时,它执行检查 - 简单的if 语句来查看索引是否超出范围。如果是,则抛出异常。如果没有抛出异常并且索引有效,则您“失去”一些时间来执行检查
  • 您的映射类型是什么?我很确定对于您的代码中的auto t,推断出mapped_type(而不是参考),这会导致mapped_type 副本。试试auto&amp; t
  • 哇!那是罪魁祸首。将auto t 更改为auto&amp; t 并保持map::at 它运行得非常快!

标签: c++11 thread-safety stdmap


【解决方案1】:

您观察到的性能差异可归因于对象复制

auto t = m.at(array1.at(i));

根据template argument deduction规则(同样适用于auto说明符),在上面的语句中,t被推导为mapped_type,触发对象复制。

您需要将t 定义为auto&amp; t 才能推导出为mapped_type&amp;

相关对话:`auto` specifier type deduction for references

【讨论】:

  • 我的错。我认为auto 会更复杂,并且会密切关注确切的方法签名(包括参考)。
  • 嗯,C++ 页面绝对不是一个容易(或令人愉快)阅读的!
  • @GeorgeKastrinis,但那样就不会那么灵活了。默认情况下,它总是生成一个非常量非引用副本,您可以轻松地覆盖这两个功能。如果规则跟踪了您调用的函数的类型,那么您将始终需要查看该函数以确定是否需要添加覆盖以使其成为非 const 或副本,实际上该语言不需要很容易给你这两件事(除非你通过一个不漂亮的类型特征转换器)。好的,在某些情况下这是无稽之谈,就像函数引用仍然是引用一样。
猜你喜欢
  • 2011-01-21
  • 2021-02-03
  • 1970-01-01
  • 1970-01-01
  • 2015-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多