c - 全局变量在 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;
}
与c
全局变量。每次循环迭代中是否c
“从全局范围重新读取”?毕竟,它可能已经被其他一些执行其他功能的线程改变了,对吧?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]*c
vs.的a[i]*c_cp
问题吗?
我自己的研究
解决方案
任何相当聪明的编译器都会优化您的代码,使其表现得像您的第二个代码片段。使用static
不会有太大变化,但如果你想确保每次迭代都读取,那么使用volatile
.
关于来自不同线程的更改的要点。就单线程执行而言,编译器将保持代码的完整性。这意味着它可以重新排序您的代码、跳过某些内容、添加一些内容——只要最终结果仍然相同。
对于多个线程,您的工作是确保事情仍然以特定的顺序发生,而不仅仅是最终结果是正确的。确保是内存屏障的方法。这是一个有趣的话题,但除非你是专家,否则最好避免。
推荐阅读
- ios - 为什么我的多通道映射不能正常工作?
- javascript - 如何正确解析包含非常大数字的 JSON 字符串?
- amazon-web-services - 没有在 MediaPackage 中创建清单,从 AWS 控制台工作
- android - 在 setClickListener 期间以编程方式设置渐变不起作用。为什么?
- go - 如何将变量值 addr、[]net.IP 转换为字符串?
- bash - 从另一个脚本调用时,Curl 无法打开多部分文件
- oracle - 如何在Oracle中添加一个策略,用户可以从表中选择所有数据,并且只能插入、更新、删除有条件的数据
- ios - 删除 UICollectionView 中的行间距?迅速
- android - Android 分页库 - 将 Room DataSource.Factory<*, DatabaseModel> 映射到 DataSource.Factory<*, PresenterModel>
- c# - 将值插入 mysql 数据库无法按预期工作