我有一个循环像这样:
uint32_t result = 0;
for ( int i = 0; i < CONSTANT; ++i )
{
result ^= expr;
}
return result;
总的来说,GCC在这段代码上做得很好。它完全展开循环并为expr
生成最佳代码。但是,它执行result
XOR CONSTANT
次。它可以累积部分结果并分层地将它们异或在一起。
我怀疑如果我用宏手动展开它,我可以手动完成它(CONSTANT
并不大),但我想知道为什么它看不到这一点,或者如果我做了一些阻止它由于一些《双城之战》 C++ 规则。
3条答案
按热度按时间xa9qqrwz1#
在这里积累部分结果可能没有好处。如果你使用分治策略(XOR偶数与奇数减半大小,然后重复,每次将操作数减半),你仍然会完成
O(CONSTANT)
的工作(一半的工作加上四分之一的工作加上八分之一的工作,等等,最终执行CONSTANT - 1
操作)。在块中累积部分结果的行为相同。基本上,你必须有
CONSTANT - 1
XOR操作。由于这些是固定宽度的寄存器,而不是增长任意精度的整数,因此每个XOR的工作是相同的。除非将expr
工作并行化,否则您不太可能从更复杂的方法中获得任何好处。xbp102n02#
对于你的循环,要么
expr
不依赖于i
,在这种情况下gcc
应该完全优化掉循环,要么gcc
可以 * 仍然 * 优化掉它(因为循环边界是恒定的,整个循环可以预先计算)。好像是fails in the latter case,除非你optimize for
-march=haswell
。这看起来很奇怪,但我确实见过这种behavior before。在任何情况下,您提到
expr
编译为两条指令。为xor
添加3条指令,循环增量和测试指令,您已经为这个循环添加了5条指令,这甚至超过了高端x86 CPU的退休率,因此在这里寻找额外的指令级并行性没有任何好处(除非您正在编译一个具有更高宽度的非x86 arch?).1..
2.我们只能猜测,因为你确实紧紧地守护着
expr
的秘密。3duebb1j3#
在严格的XOR计算中,从技术上讲,XOR计算中不会有超过两个值,因为它在逻辑上没有意义,并且只有当我们在像var1 ^ var2 ^ var3这样的链中超过两个XOR值时,才会告诉我们所有数字的组合奇偶性,因此从技术上讲,通过使用两个以上的值,你应该只能告诉它的奇偶性,无论结果是偶数还是奇数。
然而,在大多数编程语言中,编译器会自动创建一系列级联的XOR操作,每次只处理两个值,然后将该结果与下一个值进行XOR,直到处理完所有值,所以实际上不可能有真正的批量XOR链或列表作为表达式,尽管我们可以以这种方式编写它们,编译器处理细节。