在函数定义中使用引用参数:performance
Using reference arguments in function definition: perfomance?
是否知道两种变体中哪一种工作速度更快,或者它们相同,或者比较不正确。
Vector test(Vector &vec)
{
// return modified vector, or write directly to vec,
// or do not return anything, but access vec anyway
}
Vector test(Vector vec)
{
// same (but no reference)
}
我之所以问,是因为我可能知道,为Direct3D游戏创建最佳优化代码。
UPDATE:我说的是来自xnamath.h(d3d-sdk)的XMVECTOR——16字节,4个浮点。
这不是一种有用的概括方法。
在谷歌上搜索XMVECTOR
,我得到
typedef __m128 XMVECTOR;
因此,尽管是16个字节,但它都是一个SSE机器寄存器,所以您当然应该按值传递这个吸盘。引用寄存器中的某个内容只会有将其强行放入堆栈的风险。
EDIT:即使您没有使用上面的typedef,XMVECTOR
仍然可能是一种特殊类型,编译器会对其进行不同的处理。请注意有关XBox平台的注意事项。在任何情况下,我下面所说的都是双倍的:
将微观优化视为惯用方法是错误的。微观优化从机器代码开始。这里的起点应该是探查器指向的任何机器指令,因为任何程序中都有太多的微小部分,你不会仅仅凭直觉就能找到慢的部分。
如果你刚刚开始你的第一个优化项目,你应该研究不同的评测工具(告诉你程序的哪个部分很慢),并熟悉其中一个。一旦你深入到足够的程度,当你无法通过调整源代码所说的来提高速度时,你就必须开始分析机器指令。这需要熟悉CPU及其指令集的细节。只有这样,您才能有效地开始调整源代码中关于如何做小事的细微差异。
如果你对CPU如何执行指令不太了解,就不要急于优化这类事情。考虑到程序的算法和整体结构都很重要,这完全是浪费时间。
小时>
编辑:有关16字节长的Vector
的详细信息,请参阅底部
如果向量有几个以上的元素(或者元素本身相当大),那么第一个很可能会快得多。
然而,正如他们所说,"细节是魔鬼"。在某些特定情况下,第二种情况可能确实更快。这将是一个例外,而不是规则,但这仍然是一种可能性。
在第二种情况下,向量正在被复制[除非编译器能够内联代码,并且编译器能够意识到正在发生的事情,并删除额外的副本]。如果向量有10000个元素,那就是向量中任何元素的10000个副本。
在第一种情况下,从调用函数传递给调用方函数的所有内容都是一个指针。另一方面,由于它是一个引用,因此生成的代码必须再进行一次内存引用才能读取内容。因此,如果向量很小,并且test
函数对vec
变量进行了多次访问,那么间接操作的额外开销可能比内容的副本"更糟"。
如果有疑问,请对这两种解决方案进行基准测试。
确保基准是有代表性的-你可以把10k个元素的速度提高100倍,然后当元素数量少于20时,速度降低2倍-平均值为11…
编辑:由于问题已经更新,我不得不补充一点,"由于Vector
对象很小",因此两个选项之间的显著差异可能性要小得多。在32位系统上,pass-by-reference选项可能仍然有一点好处[但是,正如我在上文中所说,它与更复杂的Vector
内容访问相平衡]。在64位系统上,传递两个寄存器值可能比传递一个引用更快。
再次,在"正常"类型负载下进行基准测试。
通过引用传递的向量参数会更快,如果向量中有许多元素,则会更快。这样,您就可以避免在本地复制上花费的时间。
您应该始终通过引用传递对象,除非您需要传递地址,例如,如果您也想允许空指针。按值传递对象意味着:
- 正在复制
- 对象切片
这两者你都不想发生。
过早的优化是万恶之源
这主要是过早的优化。这也是一个微观优化。因此,它需要更多关于Vector
类型和所需用法、编译器以及许多其他因素的知识。
这两者并不相等;后者将不接受右值,并允许函数更改向量。您应该使用const&
使它们真正相似。
你说这是一款D3D应用程序;在这种情况下(除了预计算),您真的希望在GPU上进行向量和矩阵计算。简单的探查器对此没有帮助,您需要同时探查CPU和GPU代码。
正如@Potatoswatter所注意到的,这是一种CPU将比通过引用传递时优化得更多的类型。
- 将const引用参数初始化为默认参数会导致悬空引用吗
- 具有常量引用参数的函数模板专用化
- C++:常量引用参数
- 字符串引用参数的效率C++
- 通过非常量引用参数修改常量引用参数
- 如何将指针变量作为引用参数传递?
- C++初始化 std::function 时如何将占位符绑定到引用/引用参数?
- 移动类的成员作为常量引用参数传递
- C++带有适用于左值和右值的引用参数的函数
- constexpr 函数的常量引用参数:gcc/msvc vs clang/icc
- 如何使用类型特征将函数的通用引用参数限制为 r 值引用?
- 委托构造函数和引用参数
- 对 const 引用参数使用默认值会导致崩溃
- 为什么我们不允许将纯引用参数传递给 std::thread,但允许传递原始指针?
- 为什么我需要将默认引用参数定义为 const 以便为其分配一个左值?
- 将非左值作为常量引用参数传递.临时是在本地作用域还是在调用方作用域中创建的?
- 如何强制函数仅接受左值引用参数
- 模板引用参数推断失败C++
- 非类型引用参数可以在运行时修改,这是否意味着模板可以在运行时实例化?
- 将unique_ptr作为引用参数或常量传递unique_ptr引用