全局变量在C中的紧密循环中读取



假设我在C中有一个紧循环,在其中我使用全局变量的值来进行一些算术运算,例如

double c;
// ... initialize c somehow ...
double f(double*a, int n) {
double sum = 0.0;
int i;
for (i = 0; i < n; i++) {
sum += a[i]*c;
}
return sum;
}

其中CCD_ 1是全局变量。是CCD_ 2";从全球范围重新阅读";在每次循环迭代中?毕竟,它可能会被其他线程执行其他函数所更改,对吧?因此,在循环之前获取c的本地(函数堆栈(副本并仅使用此副本,代码会更快吗?

double f(double*a, int n) {
double sum = 0.0;
int i;
double c_cp = c;
for (i = 0; i < n; i++) {
sum += a[i]*c_cp;
}
return sum;
}

虽然我还没有指定如何初始化c,但让我们假设它是以某种方式完成的,因此在编译时值是未知的。此外,c在整个运行时实际上是一个常数,也就是说,作为程序员,我知道它的值不会改变。我可以让编译器了解这些信息吗?例如,在全局范围内使用static double c?这是否改变了a[i]*ca[i]*c_cp的问题?

我自己的研究

  • 阅读例如";全局变量";在本节中,似乎很清楚,获取全局变量的本地副本是可行的。然而,他们想要更新全局变量的值,而我只想读取它的值
  • 使用godbolt,我没有注意到cc0以及double cstatic double c在装配中的任何实际差异

任何相当智能的编译器都会优化您的代码,使其表现为您的第二个代码片段。使用static不会有太大变化,但如果您想确保每次迭代都能读取,那么就使用volatile

关于来自不同线程的更改,这是一个很好的观点。只要是单线程执行,编译器就会保持代码的完整性。这意味着它可以重新排序代码、跳过某些内容、添加某些内容——只要最终结果仍然相同。

对于多个线程,您的工作是确保事情仍然按照特定的顺序发生,而不仅仅是确保最终结果是正确的。确保这一点的方法是内存障碍。这是一个有趣的话题,但除非你是专家,否则最好避免。

一旦所有内容都转换为机器代码,您将不会有任何差异。如果c是全局的,则对c的任何访问都将引用c的地址,或者很可能,在紧密循环中,c将保留在寄存器中,或者在最坏的情况下保留在L1高速缓存中。

在Linux机器上,您可以轻松地生成程序集并检查生成的代码。

您还可以运行基准测试。

相关内容

  • 没有找到相关文章

最新更新