当sizeof(myPOD)对于x64上的传递值太大时
When is sizeof(myPOD) too big for pass by value on x64?
当涉及到大小高达8字节的结构时,我希望没有什么不同,但更大的POD类型呢?当类型的大小超过机器字大小时,传递值是否会变得更昂贵,或者是否有其他因素(如缓存行大小)会影响性能?
我主要对x64感兴趣,但也可以随意加入一些x86的数字。
澄清:
- 我可能想得太狭隘了,因为我不知道在这方面起作用的一切(寄存器、调用约定、编译器优化)。我主要对微软的C++编译器感兴趣,它只使用__fastcall
- 我很感兴趣的是,在了解架构、类型大小、缓存大小等的参数传递方面,是否有任何通用的建议。比如:"当类型小于N字节时,更喜欢按值传递类型。"其中N是可以从我们所知道的东西中派生出来的东西
您混淆了两个独立的问题。您可以通过值传递任何对象(只要它是可复制的)。
它是否会在寄存器中或堆栈中传递取决于实现,特别是所使用的调用约定。
在某些调用约定下,大于8字节(通用寄存器大小)的参数将在堆栈上传递。在其他调用约定下,它们可以简单地划分为几个寄存器。
在某些情况下,对象可能是从不在寄存器中传递的,无论其大小如何。
类似地,SIMD值(SSE/AVX)在某些调用约定中可以在寄存器中传递,但在其他调用约定中总是放在堆栈中。标量浮点值也是如此。
但你所问的并不能得到真正有意义的回答。复制对象的速度受对象大小的影响,是的。如果对象是POD类型,并且适合寄存器,则可以使用简单的mov
指令来复制。编译器是否执行取决于编译器。
很明显,对象越大,占用的缓存空间就越多,这意味着会有更多的缓存未命中。
但这一切都太模糊了,几乎毫无用处。我们不知道您的对象是什么样子的,也不知道代码对它做了什么。如果您有一个特定的类型,那么编写一个基准测试,看看编译器如何处理它。
响应您的编辑
我很感兴趣的是,当涉及到知道架构、类型大小、缓存大小等的参数传递时,是否有任何通用的建议。比如:"当类型小于N字节时,更喜欢按值传递。
首先,相信你的编译器。在许多情况下,它会积极优化拷贝,因此即使按值传递大对象,也不太可能是一个可衡量的问题。
其次,你看到的是一个微观优化,无论哪种方式都不太可能产生显著的差异。对于小对象,通过值传递可以避免指针间接寻址,因此可能会稍微快一点。在某种程度上,这会被复制成本所淹没(假设对象被复制,请参见上文)。对于非常大的对象(为了便于论证,假设500字节或以上,太大以至于通常无法访问它),您绝对应该通过引用传递。
但是对于8、16、24、40字节的对象呢?谁知道呢?谁在乎?它不太可能在实际代码中产生可衡量的差异。
这让我想到了两条经验法则:
- 做一些看起来很自然的事情:如果传递副本使代码更简单或更干净,那么就这样做
- 如果性能很重要,那么(1)确保您所看到的内容实际上对您的性能有任何明显的影响。衡量它。如果它影响性能,那么它是可以衡量的。如果不能衡量,那么根据定义,性能的差异就不会明显
简而言之:
- 对于基元类型,按值传递
- 对于非常大的类型,通过引用传递
- 对于其他事情,不要再担心,把时间花在有成效的事情上
您应该关注两件事-数据复制和堆栈使用
数据复制需要时间。结构越大,复制它所需的时间就越长。它是否是一种性能取决于你多久做一次,以及你的代码的性能要求是什么。
堆栈很大,但不是无限的。按值传递大型结构,尤其是与递归结合使用时,很容易导致其溢出。
对于x86_64(使用WIN64或Linux约定),在寄存器中传递数据是一个较小的点。如果每个参数最多8个字节,则前6个在寄存器中传递,这样会更快。对于x86,大多数约定都无法做到这一点(但是Linux内核使用3个寄存器作为参数)
使用药店稍微快一些。但是,与复制8个字节和1000个字节的差异相比,使用堆栈或寄存器传递8个字节之间的差异很小。
- 如何使我的 sizeof sum 结构与空参数包一起工作
- 同一对象的"sizeof"的不同答案
- 为什么数组大小信息可用于"sizeof"运算符和 delete[] 运算符,但在将数组作为参数传递到
- 为什么 sizeof 在 C++ 中给出不正确的字节数?
- sizeof(size_t) 可以小于 sizeof(int) 吗?
- 字符串数组上的 sizeof 运算符以 C++ 为单位给出不同的输出
- 为什么 sizeof(ar)/ sizeof(ar[0]) 在传递给函数时无法在向量上正常工作?
- 为什么 MSVC _count_of实现将 0 添加到 sizeof 的结果中?
- alignas() 对 sizeof() 的影响 - 强制性的?
- 在C++中,运算符 sizeof 返回什么数据类型?
- sizeof 函数如何在带和不带位字段的结构上工作?(填充)
- s.length 和 sizeof(a) 有什么区别?
- sizeof(enum) 可以不同于 sizeof(std::underlying_type<Enum>::
- 如何将数组传递给使用 sizeof 的函数?
- sizeof(size_t) 和 sizeof(ptrdiff_t) 什么时候会有所不同?
- " sizeof "操作员在编程中真的很重要吗,尤其是在构建大型应用程序时?
- 在QScopedPointer的实现中使用sizeof
- Sizeof返回的是指针大小,而不是数组大小.有其他方法可以找到尺寸吗
- 为什么sizeof函数在这里不能正常工作
- 当sizeof(myPOD)对于x64上的传递值太大时