我想知道在检查之后设置32位变量是否比设置它更快?例如。变量a是uint32
if( a != 0)
{
a = 0;
}
或
a = 0;
代码将在循环中运行,它将运行多次,因此我希望减少运行代码的时间。 注意变量a大部分时间都是0,因此如果检查32位变量或设置变量更快,问题可能会缩短。提前谢谢!
编辑:感谢所有对此问题发表评论的人,我创建了一个for循环,并测试了分配和if-ing 10万次。事实证明,分配速度更快。(if-ing为54ms,分配为44ms)
答案 0 :(得分:6)
你所描述的被称为"静音商店"优化
PRO:避免不必要的商店。
这可以减少商店加载转发缓冲区的压力,转发缓冲区是现代无序CPU的一个组件,在硬件上非常昂贵,因此通常尺寸过小,因此也是性能瓶颈。在Intel x86 CPU上,有一些性能事件监控计数器(EMON)可用于调查这是否是程序中的问题。
有趣的是,它还可以减少程序的负载数量。一,SW:如果存储没有被淘汰,编译器可能无法证明不写入由不同变量占用的内存,所谓的地址和指针消歧问题,所以编译器可能会生成不必要的重载这样可能但实际上不是冲突的内存位置。消除商店,其中一些loD也可能被淘汰。其次,硬件:大多数现代CPU都有存储来加载依赖性预测器:更少的存储增加了准确性。如果预测了依赖性,则负载实际上可能不由硬件执行,并且可能被转换为寄存器以进行寄存器移动。这是威斯康星大学最近针对英特尔和苹果提出的专利诉讼的主题,其奖励超过数亿美元。
但消除不必要存储的最重要原因是避免不必要地弄乱缓存。最终必须将脏缓存行写入内存,即使没有更改。浪费力量。在许多系统中,它最终会写入闪存或SSD,浪费功率并消耗设备的有限写周期。
这些考虑推动了静音商店的学术研究,例如http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.28.8947&rep=rep1&type=pdf。然而,一个快速的谷歌学者搜索显示这些论文主要是2000-2004,我知道没有现代的CPU实现真正的静默存储消除 - 实际上硬件读取旧值。然而,我怀疑这种静音存储的缺乏主要是因为CPU设计暂停了十多年,因为重点从台式机转向手机。现在手机几乎赶上了2000年代桌面CPU的复杂性,它可能会再次出现。
CON:消除软件中的静默存储需要更多指令。更糟糕的是,它需要一个分支。如果分支不是很可预测,那么由此产生的分支误预测将消耗任何节省。有些机器的指令可以让你在没有分支的情况下消除这种商店:例如英特尔的带有条件矢量掩码的LRBNI矢量存储指令。我相信AVX有这些说明。如果您或您的编译器可以使用这些指令,那么成本只是旧值的加载和向量比较,如果旧值已经在寄存器中,那么只是比较。
顺便说一句,您可以在不完全取消商店的情况下获得一些好处,但可以将其重定向到安全地址。相反,如果
如果a [i]!= 0则a [i]:= 0
待办事项
ptr = a + I; if * ptr == 0然后ptr。:=& safe; * PTR:= 0
仍然在做商店,但没有弄脏那么多缓存行。如果伪造一个条件存储指令,我已经习惯了这种方式。编译器不太可能进行这种优化。
所以,不幸的是,答案是"它取决于"。如果您使用的是矢量蒙版机器或GPU,并且静音商店非常常见,例如,超过30%,值得考虑。如果在标量代码中,可能需要更多像90%无声。
理想情况下,自己测量一下。虽然很难做出真实的测量。
我会从最优化的情况开始:
char a [1024 * 1024 * 1024]; //零填充 const int cachelinesize = 64; for(char * p = a; p
这里消除了每个商店 - 确保编译器仍然发出它们。良好的分支预测等
如果此限制案例没有显示任何好处,则您的实际代码不太可能。
如果是这样的话,我在上个世纪就跑了这么一个基准。静默存储代码快2倍,因为完全内存绑定,静默存储在回写缓存上不生成脏缓存行。重新检查,然后尝试更现实的工作量。
但首先,衡量你是否有内存瓶颈。
顺便说一下:如果静默存储消除的硬件实现变得普遍,那么你永远不会想用软件来实现它。
但目前我知道在商用CPU中没有静音存储消除的硬件实现。
随着ECC变得越来越普遍,静默存储消除变得几乎是免费的 - 因为在许多情况下你必须读取旧的字节以重新计算ECC。
答案 1 :(得分:0)
分配会更好,因为首先<i>
语句是多余的,如果你省略它会使它更清楚,分配也应该更快,即使你不太确定你可以只需创建一个简单的函数来测试它是否有if
语句。