alloca的性能

问题描述

这些天来,我经常使用alloca来分配临时缓冲区。在我的应用程序(信号处理)中,这是常见的需求。

问题是:

分配多个数组时,一次使用alloca更好(在性能方面)?

赞:

float *array1 = (float*)alloca(4096 * 4);
float *array2 = array1 + 1024;
float *array3 = array2 + 1024;
float *array4 = array3 + 1024;

或者像这样多次使用它:

void *array1 = (float*)alloca(4096);
void *array2 = (float*)alloca(4096);
void *array3 = (float*)alloca(4096);
void *array4 = (float*)alloca(4096);

我的意思是,它可能要做的就是减少堆栈指针,并可能执行“堆栈探针”,这取决于大小,所以这没关系吗?

解决方法

我确信您知道,使

alloca的速度比malloc快,原因与执行分配/取消分配的方式以及所使用的内存部分有关。如评论中所述,它也很容易出错。

到目前为止,我的猜测是,在未经优化的情况下,重复alloca的第一个版本比使用间接寻址要快,而且确实在经过一些基准测试之后,这一点已经得到证实:

enter image description here

使用google benchmark,clang 10.0,C ++ 20 std进行了测试,并且没有优化。使用功能运行与OP相似的代码,重复测试以得到恒定的结果。

#include <alloca.h>

void alloc1(){
    float *array1 = (float*)alloca(4096 * 4);
    float *array2 = array1 + 1024;
    float *array3 = array2 + 1024;
    float *array4 = array3 + 1024;
}

void alloc2(){
    void *array1 = (float*)alloca(4096);
    void *array2 = (float*)alloca(4096);
    void *array3 = (float*)alloca(4096);
    void *array4 = (float*)alloca(4096);
}

static void alloca1_test(benchmark::State& state) {
    for (auto _ : state) {
        alloc1();
        //benchmark::DoNotOptimize();
    }
}
BENCHMARK(alloca1_test);

static void alloca2_test(benchmark::State& state) {
    for (auto _ : state) {
        alloc2();
        //benchmark::DoNotOptimize();
    }
}
BENCHMARK(alloca2_test);

O3 otpimization添加了,正如人们所期望的那样,测试结果将趋于均匀,多个alloca仍然始终略快一些,但性能差异可以忽略不计。如您所说,基本上是相同的。使用一个或另一个似乎没有什么不同。

enter image description here

免责声明:

为了最好地了解您的程序的性能,与此处进行的单独测试相比,集成测试将为您提供更准确的阅读结果。 buils工具以及环境也会影响最终结果,要完全准确地评估选项的性能,您必须自己对其进行测试。

,

alloca的用处在于,如果您不知道预先数组的大小。

对于给定的代码,它与简单编写没有什么不同

float array1[4096];
float array2[4096];
float array3[4096];
float array4[4096];

坦率地说,我认为没有必要进行基准测试; alloca只是增加了堆栈指针来为您的分配腾出空间,就像声明这些数组一样。