0

我正在写一些对性能至关重要的东西,想知道如果我使用它是否会有所作为:

int test( int a, int b, int c )
{
    // Do millions of calculations with a, b, c
}

或者

class myStorage
{
public:
  int a, b, c;
};

int test( myStorage values )
{
   // Do millions of calculations with values.a, values.b, values.c
}
  • 这基本上会导致类似的代码吗?访问类成员是否有额外的开销?

我确信这对于 C++ 专家来说是清楚的,所以我现在不会尝试为它编写一个不切实际的基准测试

4

8 回答 8

5

编译器可能会均衡它们。如果它有任何大脑,它会将values.avalues.b、 和复制values.c到局部变量或寄存器中,这也是简单情况下发生的情况。

相关格言:

  1. 过早的优化是万恶之源。

  2. 写下来,这样你就可以在六个月后的凌晨 1 点阅读它,并且仍然理解你想要做什么。

  3. 大多数时候,重要的优化来自于重构你的算法,而不是变量访问方式的微小变化。是的,我知道有例外,但这可能不是其中之一。

于 2010-05-19T16:38:39.747 回答
4

这听起来像是过早的优化。

话虽如此,存在一些差异和机会,但它们会影响对函数的多次调用,而不是函数的性能。

首先,在第二个选项中,您可能希望将 MyStorage 作为常量引用传递。因此,您的编译代码可能会将单个值推送到堆栈中(以允许您访问容器),而不是推送三个单独的值。如果您有其他字段(除了 ac),发送 MyStorage 不作为参考实际上可能会花费您更多,因为您将调用复制构造函数并基本上复制所有其他字段。所有这些都是每次调用的费用,而不是函数内的费用。

如果您在函数中使用 ab 和 c 进行大量计算,那么您如何传输或访问它们实际上并不重要。如果您通过引用传递,初始成本可能会略高(因为您的对象,如果通过引用传递,可能在堆上而不是堆栈上),但是一旦第一次访问,您机器上的缓存和寄存器可能会意味着低成本访问。如果您按值传递了对象,那么这真的没关系,因为即使最初,这些值也会在堆栈附近。

对于您提供的代码,如果这些是唯一的字段,则可能没有区别。“values.variable”仅被解释为堆栈中的偏移量,而不是“查找一个对象,然后访问另一个地址”。

当然,如果您不购买这些参数,只需将局部变量定义为函数中的第一步,从对象中复制值,然后使用这些变量。如果您真的多次使用它们,则此副本的初始成本无关紧要:)

于 2010-05-19T16:39:27.073 回答
0

如果您无法分析程序,请打印出代码片段的汇编语言。

一般来说,更少的汇编代码意味着更少的执行指令,从而提高性能。这是一种在分析器不可用时粗略估计性能的技术。

汇编语言列表将允许您查看实现之间的差异(如果有)。

于 2010-05-19T18:46:05.097 回答
0

不,你的 CPU 会缓存你一遍又一遍地使用的变量。

于 2010-05-19T16:40:04.593 回答
0

我认为有一些开销,但可能不会太多。因为对象的内存地址会存放在栈中,指向的是堆内存对象,那么就访问实例变量。

如果将变量 int 存储在堆栈中,它会非常快,因为该值已经在堆栈中,并且机器只是去堆栈将其取出来计算:)。

它还取决于您是否将类的实例变量值存储在堆栈中。如果在 test() 中,你确实喜欢:

int a = objA.a;
int b = objA.b;
int c = objA.c;

我认为这将是几乎相同的表现

于 2010-05-19T16:41:15.230 回答
0

如果您真的在编写性能关键代码并且您认为一个版本应该比另一个更快,请编写两个版本并测试时序(使用正确的优化开关编译的代码)。您甚至可能希望查看生成的汇编代码。很多事情都会影响非常微妙的代码片段的速度,比如寄存器溢出等。

于 2010-05-19T16:42:22.327 回答
0

你也可以开始你的功能

int & a = values.a;
int & b = values.b;

尽管编译器应该足够聪明,可以在幕后为你做这件事。一般来说,我更喜欢传递结构或类,这通常会使函数的用途更清楚,而且您不必在每次考虑另一个参数时都更改签名。

于 2010-05-19T16:43:12.340 回答
0

与您之前的类似问题一样:它取决于编译器和平台。如果有任何差异,那将是非常小的。

堆栈上的值和对象中的值通常使用指针(堆栈指针或this指针)和一些偏移量(函数堆栈帧中的位置或类内的位置)来访问。

以下是一些可能会产生影响的情况:

  • 根据您的平台,堆栈指针可能保存在 CPU 寄存器中,而this指针可能不保存。如果是这种情况,访问this(可能在堆栈上)将需要额外的内存查找。

  • 内存位置可能不同。如果内存中的对象大于一个缓存行,则这些字段分布在多个缓存行上。仅将相关值放在堆栈帧中可能会提高缓存效率。

但是,请注意我在这里使用“可能”这个词的频率。唯一确定的方法是测量它。

于 2010-05-19T16:44:20.307 回答