C++ 使用大局部变量(C+;+;)优化频繁调用的函数
假设有一个函数我需要调用数百万次。这个函数执行的算术运算并不繁重,所以唯一重要的是所有变量分配的速度有多快。我们还假设变量总是在堆栈上分配的。 最简单的例子是:C++ 使用大局部变量(C+;+;)优化频繁调用的函数,c++,optimization,stack-memory,static-memory-allocation,C++,Optimization,Stack Memory,Static Memory Allocation,假设有一个函数我需要调用数百万次。这个函数执行的算术运算并不繁重,所以唯一重要的是所有变量分配的速度有多快。我们还假设变量总是在堆栈上分配的。 最简单的例子是: void doSomething(){ int aReallyLargeVariable[10000]; ...performing a few light operations on that variable and returning nothing... } 我知道当函数返回所有变量时,它的变量都会被销毁,所以
void doSomething(){
int aReallyLargeVariable[10000];
...performing a few light operations on that variable and returning nothing...
}
我知道当函数返回所有变量时,它的变量都会被销毁,所以将此变量设为静态或全局缓存不是更好吗?优化它的最佳方法是什么?不是分配会导致性能问题。问题是如何初始化它,以便
int aReallyLargeVariable[10000];
不会花很多时间的
int aReallyLargeVariable[10000] = {0};
行。此外,动态创建大型对象可能会导致问题
如果您的函数没有很重的逻辑,并且只使用基本类型,只需将其定义为inline
,而不必担心性能
如果需要定义大量对象,请考虑另一种数据结构,如
堆栈
或向量
,它们不需要1000个或更多元素,但分配不会导致性能问题。问题是如何初始化它,以便
int aReallyLargeVariable[10000];
不会花很多时间的
int aReallyLargeVariable[10000] = {0};
行。此外,动态创建大型对象可能会导致问题
如果您的函数没有很重的逻辑,并且只使用基本类型,只需将其定义为inline
,而不必担心性能
如果需要定义大量的对象,请考虑另一种数据结构,如
堆栈
或向量
,它不需要1000个或更多元素来优化此函数,考虑到它被多次调用,第一步必须是不要局部声明大变量
。当您这样做时,会发生一些事情:
- 由于您在本地声明了数组,并且可能只使用了几个值,因此浪费了大量堆栈空间
- 此声明导致的堆栈操作(push/pop)可能超过函数必须完成的实际工作
最好在其他地方声明此数组(如果必须,则全局声明),并传入指向该数组的指针。这样,您还可以重用内存,而不浪费时间重新分配。要优化此函数,考虑到它被多次调用,第一步必须是
不要在本地声明大变量。当您这样做时,会发生一些事情:
- 由于您在本地声明了数组,并且可能只使用了几个值,因此浪费了大量堆栈空间
- 此声明导致的堆栈操作(push/pop)可能超过函数必须完成的实际工作
最好在其他地方声明此数组(如果必须,则全局声明),并传入指向该数组的指针。通过这种方式,您还可以重用内存,而不会浪费时间重新分配。我建议将它们分配为静态,这样整个int areallylargevaluate[10000]
不会在每次调用函数时分配和释放如此巨大的内存量,从而影响堆栈。但是,您也可以声明int-areallylarge变量[10000]代码>
作为全局变量,但许多开发人员讨厌在代码中使用大量全局变量。如果您不喜欢函数中的静态变量(由于并发执行等原因),也不喜欢全局变量,则可以在全局范围中将变量声明为静态变量,以便变量名仅在其声明的上下文中有效,这样可以防止链接器错误
Source.cpp
static int aReallyLargeVariable[10000];
void myFunction()
{
aReallyLargeVariable[1] = 10;
}
int aReallyLargeVariable[10000]; /* No name collisions during linking */
Object.cpp
static int aReallyLargeVariable[10000];
void myFunction()
{
aReallyLargeVariable[1] = 10;
}
int aReallyLargeVariable[10000]; /* No name collisions during linking */
注意:只要您不决定将Source.cpp包含在Object.cpp中,或者将Source.cpp包含在Object.cpp>中,或者将包含在中,我建议将它们分配为静态变量,以便整个int areallyllarge变量[10000]
不会在每次调用函数时分配和释放如此巨大的内存量,从而影响堆栈。但是,您也可以声明int-areallylarge变量[10000]代码>
作为全局变量,但许多开发人员讨厌在代码中使用大量全局变量。如果您不喜欢函数中的静态变量(由于并发执行等原因),也不喜欢全局变量,则可以在全局范围中将变量声明为静态变量,以便变量名仅在其声明的上下文中有效,这样可以防止链接器错误
Source.cpp
static int aReallyLargeVariable[10000];
void myFunction()
{
aReallyLargeVariable[1] = 10;
}
int aReallyLargeVariable[10000]; /* No name collisions during linking */
Object.cpp
static int aReallyLargeVariable[10000];
void myFunction()
{
aReallyLargeVariable[1] = 10;
}
int aReallyLargeVariable[10000]; /* No name collisions during linking */
注意:只要您不决定将源.cpp包含在对象中,它就可以工作。cpp或反之亦然,将变量作为函数的一个参数,并对许多函数调用使用相同的变量?函数是递归调用还是并发调用?以及-因为您已经知道替代设计,你能分享你的基准测试结果吗?就像任何性能问题一样-检查生成的代码/分析它/实际检查它在做什么。我猜编译器在这两种情况下都会生成相同的代码。将变量作为函数的参数,并在许多函数调用中使用相同的变量?函数是递归调用还是并发调用?以及-因为您已经知道其他设计,你能分享你的基准测试结果吗?就像任何性能问题一样-检查生成的代码/分析它/实际检查它在做什么。我猜编译器在这两种情况下都会生成相同的代码;这些操作只是更改一个寄存器值