在 C++ 中,当一个数组的元素在循环中多次使用时,将其分配给另一个元素会更好吗?
Posted
技术标签:
【中文标题】在 C++ 中,当一个数组的元素在循环中多次使用时,将其分配给另一个元素会更好吗?【英文标题】:In C++, when an element of an array is used multiple times in a loop, is it better to assign it to an other element? 【发布时间】:2019-07-30 07:12:49 【问题描述】:假设我有一个循环可以对数组x
进行一些数学运算。在每次迭代时在循环内分配一个临时双精度还是我应该每次都使用array[i]
更好?
我所说的更好是指使用 C++ 在性能方面。我想知道 C++ 是否有一些我正在破坏的向量化或现金优化?
另外,如果我使用这个数组调用一个函数,我可能需要多次使用一个函数的值,所以我通常对函数做同样的事情。我认为这比多次调用该函数要好。
如果循环使用omp parallel
,我认为这应该是安全的,对吗?
for(int i=0; i<N; i++)
double xi = X[i];
double fi = f(xi);
t[i] = xi*xi + fi + xi/fi;
【问题讨论】:
使用临时可能会避免由于别名问题导致的额外负载(如果f(xi)
可以修改X[i]
)。
另外,f(xi)
可能不是“纯”的并且每次返回不同的值(例如rand()
)。
您只有在您衡量您的性能并发现它不符合规定的要求时才开始担心微优化>.
@n.m.同意 - 重要的关键字是 'micro',但是,仍然应该从一开始就考虑一些通用的优化模式,例如。 G。使用(并实现)移动语义,在合理的情况下,reserve
ing std::vector
的容量,如果事先知道大小,使用 std::map::find
的结果而不是进行第二次查找,...
【参考方案1】:
elcuco 是正确的。任何值得一提的编译器都可以优化出这种微不足道的东西。这里重要的是代码可读性,我个人认为X[i]
在这种情况下更容易查看。
我会注意到,如果您反复发表很长的陈述,即X.something.something.darkside[i][j]
,使用明确命名的引用(即auto & the_emperor = X.something.something.darkside[i][j]
)可能是有意义的。
【讨论】:
【参考方案2】:现代编译器(过去 10 年)将优化它。不用担心。
编辑:
这已在 *** 中讨论过几次: Will compiler optimize and reuse variable In C++, should I bother to cache variables, or let the compiler do the optimization? (Aliasing)
这个官方documentation explains它,恕我直言
-fmerge-all-constants
-fivopts
可能还有 -ftree-coalesce-vars
clang 和 MSCV 有类似的选择,请自行研究或在此处链接。
实际上,当编译器看到内存读取(变量或数组值)时,它会将其读入寄存器,除非未标记为volatile
,否则编译器可以假定它没有更改,并且将不要发出重新阅读的指示。
说了神奇的volatile
这个词:它不应该用于线程。它应该用于硬件映射内存(例如,视频卡内存或外部端口)。
【讨论】:
数组——当然。但是,如果改用std::map
,情况可能会发生变化;索引查找 (operator[]
) 很复杂,甚至可能会更改数据(如果未找到元素)——编译器能否证明删除第二次查找不会丢弃任何可见的副作用?只有这样它才能被允许优化它......
@elcuco 你有这个来源吗?我真的很好奇它是如何工作的。
@Aconcagua 如果[]
运算符标记为const
,则没有理由重新读取该值(调用该运算符)。
@elcuco 你看过std::map
吗?它甚至不提供const
版本的...
如果[]
运算符不是const
,编译器将需要重新读取该值,正如您所建议的那样(内部实现可以在每次读取后返回不同的值,即正确)。以上是关于在 C++ 中,当一个数组的元素在循环中多次使用时,将其分配给另一个元素会更好吗?的主要内容,如果未能解决你的问题,请参考以下文章