什么时候sizeof(myPOD)太大而不能在x64上传递值?

Nik*_*nić 6 c c++ 64-bit x86 x86-64

对于大小高达8字节的结构,我预计没有区别,但是更大的POD类型呢?当类型的大小超过机器字大小或是否存在可能影响性能的其他东西(如缓存行大小)时,传递值是否会变得更加昂贵?

我主要对x64感兴趣,但也可以为x86包含一些数字.

澄清:

  • 我可能的想法太狭隘,因为我不知道在这方面发挥作用的所有事情(寄存器,调用约定,编译器优化).我主要对Microsoft的C++编译器感兴趣,它只使用__fastcall.
  • 我知道架构,类型大小,高速缓存大小等参数传递时是否存在任何一般性建议.例如:"当它小于N个字节时,更喜欢按值传递类型." 其中N是可以从我们所知道的东西中得到的东西.

jal*_*alf 7

你混淆了两个不同的问题.您可以按值传递任何对象(只要它是可复制的).

它是否将在寄存器或堆栈中传递取决于实现,具体而言,取决于所使用的调用约定.

在某些调用约定下,大于8字节的参数(通用寄存器大小)将在堆栈上传递.在其他调用约定下,它们可能只是分成几个寄存器.

在某些情况下,对象永远不会在寄存器中传递,无论它们的大小如何.

类似地,SIMD值(SSE/AVX)可以在某些调用约定中的寄存器中传递,但在其他调用约定中总是放在堆栈中.标量浮点值也是如此.

但你所要求的并不能真正得到有意义的回答.复制对象的速度受对象大小的影响,是的.如果对象是POD类型,并且它适合寄存器,则可以使用简单mov指令复制它.编译器是否会这样做取决于编译器.

显然,对象越大,它占用的缓存空间就越多,这意味着你将获得更多的缓存未命中.

但这一切都是如此模糊,以至于它毫无用处.我们不知道你的对象是什么样子的,我们不知道你的代码是什么它.如果您有特定类型,请编写基准以查看编译器如何处理它.

响应您的编辑

我知道架构,类型大小,高速缓存大小等参数传递时是否存在任何一般性建议.我喜欢:"当它小于N个字节时,更喜欢按值传递类型.

首先,相信你的编译器.这将积极优化副本掉在许多情况下,所以即使你做的按值传递一个大对象,它不可能成为一个衡量的问题.

其次,你正在研究微观优化,这种方式不太可能产生显着的差异.对于小对象,按值传递可以避免指针间接,因此它可能稍快一些.在某些时候,这成为由复印的成本淹没(假设对象复制,见上文).对于非常大的对象(为了参数,让我们说500字节或更大,如此大,以至于通常无法到达它),你绝对应该通过引用传递.

但是对于8,16,24,40个字节的对象?谁知道?谁在乎?它不太可能在实际代码中产生可测量的差异.

这让我想到了两条经验法则:

  1. 做一些看似自然的事情:如果通过副本传递使你的代码更简单或更清洁,那就去做吧.
  2. 如果表现很重要,那么(1)确保你所看到的实际上对你的表现有任何明显的影响.测量它.如果它影响性能,那么就可以测量它.如果无法测量,那么根据定义,性能差异是不可察觉的.

简而言之:

  • 对于primitve类型,按值传递.
  • 对于非常大的类型,通过引用传递.
  • 对于其他一切,不要再担心,把时间花在有成效的事情上.

  • 我想我正在寻找的是x64调用约定的文档.http://msdn.microsoft.com/en-us/library/ms235286(v=vs.100).aspx很好地解释了这一点:"任何不适合8个字节的参数,或者不是1,2,4 ,或8个字节,必须通过引用传递.没有尝试在多个寄存器中传播单个参数." (2认同)