【问题标题】:Which one is faster: static array vs non-static array?哪个更快:静态数组与非静态数组?
【发布时间】:2020-01-01 14:20:53
【问题描述】:

我想知道在 C 中,如果一个函数被大量调用,静态数组是否比非静态数组更快。

第一种情况:10 个 int 的非静态 int 数组:

void useNonStaticIntArray(int i){
    int array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    array[i] = i;
}

int main(void){
    int i;
    for (i = 0; i < 1000000000; i++) {
        useNonStaticIntArray(i % 10);
    }
    return 0;
}

第二种情况:10个int的静态int数组:

void useStaticIntArray(int i){
    static int array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    array[i] = i;
}

int main(void){
    int i;
    for (i = 0; i < 1000000000; i++) {
        useStaticIntArray(i % 10);
    }
    return 0;
}

第三种情况:非静态int

void nonStaticInt(int i){
    int a;
    a = i;
}


int main(void){
    int i;
    for (i = 0; i < 1000000000; i++) {
        nonStaticInt(i % 10);
    }
    return 0;
}

第四种情况:静态int

void staticInt(int i){
    int a;
    a = i;
}


int main(void){
    int i;
    for (i = 0; i < 1000000000; i++) {
        staticInt(i % 10);
    }
    return 0;
}

所以我在 Debian 虚拟机上做了一些测试:

1)

time ./a.out 

real    0m7.733s
user    0m7.696s
sys 0m0.008s

2):

time ./a.out 

real    0m5.477s
user    0m5.416s
sys 0m0.008s

3)

time ./a.out 

real    0m5.764s
user    0m5.736s
sys 0m0.000s

4)

time ./a.out 

real    0m7.189s
user    0m7.016s
sys 0m0.032s

所以看起来静态比非静态更快,我测试了几次以确保它似乎总是(对于我测试的 10 次)是这种情况。

现在我有 3 个问题: - 我有没有做错什么事情来伪造结果? (他们是我所期望的) - 无论数组大小,总是如此吗? (从 1 到 N,N -> 最大堆栈可能值) - 它是如何运作的?

【问题讨论】:

  • 静态数组将被初始化一次。每次调用函数时都会初始化非静态数组。计时时,请确保关闭优化(或使用结果)以确保函数调用。
  • How does it really work ? - 检查the assembly generated by the compiler
  • 这是单纯的好奇吗?或者还有其他需要解决的问题吗?像这样的微优化通常不是很有用,并且通过添加 static 可以显着改变数组的语义。如果不是出于好奇,您是否在实际程序中测量过这是您程序的三大瓶颈?您是否在测量之前启用了优化(在您的实际程序中,因为您显示的代码将针对空程序进行优化)?
  • 仅供好奇,谢谢解释。
  • 第三种和第四种情况下nonStaticIntstaticInt的函数定义完全一样。

标签: c arrays performance


【解决方案1】:

你的测试并没有真正衡量任何东西。

优化编译器足够聪明,可以理解代码什么都不做;例如gcc 将静态和非静态版本都编译为空函数(即代码与{} 相同)。

https://godbolt.org/z/9r8Hxi

还要注意语义上的差异(静态数组只有一个实例,在调用之间重复使用,而非静态数组在每次调用中都不同)。这当然意味着非静态版本比静态版本需要做更多的工作(即初始化所有元素)......但这将在堆栈中(最有可能在 L1 缓存中),而静态版本将位于可能在缓存中或可能不取决于实际使用模式的全局内存中,因此认为非静态版本在某些情况下实际上可能更快并不荒谬。

但是您需要带有真实数据的真实代码(并选择硬件平台)来进行认真的分析......否则,像往常一样,这取决于。

【讨论】:

  • 一个好的编译器甚至不会调用函数或执行循环,只包含return 0;
  • 然而 OP 观察到静态版本更快的一致模式,所以似乎他们的编译器没有将两者优化为相同的东西,尽管它可以做到.
  • FWIW,我在自己的初始测试中看到了相反的模式。
  • @JohnBollinger: 或者 OP 没有使用优化。或者他/她看到了不存在的东西(人类很容易看到不存在的模式和因果关系)。
  • 是的,可能就是这样,我的错在那里,我没有把测试推得太远。尽管如此,如果数组真的通过一个重要的程序使用,我没有任何例子,但无论如何,那里会发生什么?编辑:上面的编辑给出了答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-16
  • 1970-01-01
  • 2018-07-29
  • 1970-01-01
  • 2021-10-20
  • 1970-01-01
  • 2014-07-21
相关资源
最近更新 更多