问题描述
这些天来,我经常使用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
的第一个版本比使用间接寻址要快,而且确实在经过一些基准测试之后,这一点已经得到证实:
使用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
仍然始终略快一些,但性能差异可以忽略不计。如您所说,基本上是相同的。使用一个或另一个似乎没有什么不同。
免责声明:
为了最好地了解您的程序的性能,与此处进行的单独测试相比,集成测试将为您提供更准确的阅读结果。 buils工具以及环境也会影响最终结果,要完全准确地评估选项的性能,您必须自己对其进行测试。
, alloca
的用处在于,如果您不知道预先数组的大小。
对于给定的代码,它与简单编写没有什么不同
float array1[4096];
float array2[4096];
float array3[4096];
float array4[4096];
坦率地说,我认为没有必要进行基准测试; alloca
只是增加了堆栈指针来为您的分配腾出空间,就像声明这些数组一样。