简体   繁体   English

为什么 GCC 不在这个求和循环中优化 memory 写入?

[英]Why doesn't GCC optimize away memory writes in this summation loop?

Given the following C code, why does GCC (version 10.1, x86-64, -O3) write to memory inside the loop instead of just using two registers during summation and writing the result to memory only at the end? Given the following C code, why does GCC (version 10.1, x86-64, -O3) write to memory inside the loop instead of just using two registers during summation and writing the result to memory only at the end?

void sum(unsigned int l, int *as, int *r) {
    r[0] = 0;
    r[1] = 0;
    for (int i = 0; i < l; i++) {
        r[0] += as[2 * i];
        r[1] += as[2 * i + 1];
    }
}

Generated instructions here .在此处生成说明。

My guess is that this behavior is related to GCC having concurrency "in mind".我的猜测是,这种行为与“考虑到”并发性的 GCC 有关。 You could have another thread for example reading from memory at the same address while the summation is performed.您可以有另一个线程,例如在执行求和时从同一地址的 memory 读取。
Is this the real (and only) reason?这是真正的(也是唯一的)原因吗? Is it probably even defined by a C standard?它甚至可能由 C 标准定义吗?

The compiler does not know whether as and r point into the same array, so it does not know that r[0] += as[2 * i];编译器不知道asr是否指向同一个数组,所以不知道r[0] += as[2 * i]; does not change the value of as[2 * i + 1] , which is needed in r[1] += as[2 * i + 1];不改变as[2 * i + 1]的值,这是r[1] += as[2 * i + 1]; , and similarly for other interactions between r[0] , r[1] and various elements of as . ,对于r[0]r[1]as的各种元素之间的其他交互也是类似的。

You can tell the compiler that the elements referred to via as and r do not overlap by changing the function declaration to void sum(unsigned int l, int * restrict as, int * restrict r) .您可以通过将 function 声明更改为void sum(unsigned int l, int * restrict as, int * restrict r)来告诉编译器通过asr引用的元素不重叠。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM