【问题标题】:Any performance reduction to use int instead of size_t index to access vector elements?使用 int 而不是 size_t 索引访问向量元素是否会降低性能?
【发布时间】:2016-03-08 02:53:54
【问题描述】:

如果我使用int索引访问一个向量元素,它会将整数转换为size_t,然后调用operator[](size_t)函数吗?有没有性能下降?

【问题讨论】:

  • 个人资料并亲自查看:)
  • 您可以测量并找出答案。
  • 是什么让你想到了性能下降?
  • 您可以自己比较generated code。当然它会转换它,v[0] 使用 int 显然可以。
  • 在编译器允许 int 为负数的情况下,在 x86_64 上选择 intsize_t 会产生显着的本地性能成本(因为符号扩展是相对昂贵)。显着的局部性能差异可能是也可能不是可检测的全局性能差异。编译器何时检测到特定的int 不能为负数?根据我的经验(查看生成的代码),有时会比人类显而易见的时候少。

标签: c++ vector int size-t


【解决方案1】:

这取决于 - size_t 取决于平台。

另请参阅:What's the difference between size_t and int in C++?

【讨论】:

  • @erip,你在问什么?
  • int类型的大小也取决于平台。这个答案具有误导性。
  • @mabraham - 如何误导?
  • @LeonardoHerrera 这个问题指的是 int 和 size_t。标准允许两者具有由实现确定的大小,因此决定使用其中任何一个来索引向量的结果取决于实现。答案只承认 size_t 取决于平台。
  • 我不知道为什么今天我的阅读中突然出现这个问题,但它把我送到了兔子洞。我仍然认为这个答案没有误导性,它回答了“使用int 访问向量元素是否会降低性能?”这个问题。答案仍然是“取决于”,因为size_t 是平台相关的并且保证是无符号整数!
【解决方案2】:

intsize_t 的主要区别在于int 是有符号的,而size_t 是无符号的。此外,两者的大小可能不同,因为这两种类型都是特定于平台且相互独立的。

当两个大小相同时,从intsize_t 的转换是空操作,因此不会影响性能。

当大小不同时,编译器足够聪明,可以将int 索引的部分或扩展值传递给operator [],以获取size_t,几乎没有开销,因为缩小大小需要部分加载,同时扩展size 需要为上部加载零。但是请注意,为扩展值的上部写入零并不是附加操作,因为它替换size_t 类型的索引复制上部。

因此,答案是否定的,您不会看到任何性能差异。

【讨论】:

  • 我的分析结果与您的分析相矛盾。这不是最新的编译器,所以也许对未定义行为的一些优化已经改进以修复这种效果。缺少这一点,编译器在许多情况下允许负 int,因此它是符号扩展而不是零扩展,并且在 x86_64 中,符号扩展的效率可能比零扩展低得多。
  • @JSF 请分享您的基准。众所周知,如此微小的差异很难进行基准测试,因为时间主要取决于对向量的实际访问,这取决于硬件缓存的性能。
  • 抱歉,所有分析都是属于我雇主的代码。我不能分享任何源代码,所以基准测试结果将毫无意义。几乎我所有的基准测试结果如您所料,主要是目标数据上的缓存未命中,因此生成代码中的各种 asm 代码差异都具有零影响。只有将所有这些放在一边,只查看生成的代码很重要的情况,我发现符号扩展操作很重要。
  • 根据分析结果,我们使用unsigned 作为索引的数据类型,而不是intsize_t。我们的代码比编译器可以安全地决定零扩展int 的典型代码少得多。我们的代码没有任何包含超过2**31 元素的容器。 (超过2**32 字节很常见,但超过2**31 元素还需要数年时间才能实现)。在一些模糊的情况下,需要调整使用unsigned 作为索引以避免比size_t 慢。但在更多情况下,unsigned 会更快一些,而且这些情况相加。
猜你喜欢
  • 2020-08-29
  • 2012-09-12
  • 2011-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-22
相关资源
最近更新 更多