C++,调整表达式中符号(+/-)的最有效方法
C++, most efficient way to modulate sign (+/-) in an expression
我有一个表达式
x += y;
并且,基于布尔值,我希望能够将其更改为
x -= y;
我当然可以做
if(i){x+=y;} else{x-=y;}
//or
x+=(y*sign); //where sign is either 1 or -1
但是,如果我必须迭代地这样做,我希望避免额外的计算。有没有更有效的方法?是否可以调整操作员?
if (i) {x += y;} else {x -= y;}
y * sign
可能相当昂贵(除非编译器能够确定y
保证为1或-1(。
迭代执行此操作最有效的方法是预计算所需的数据。
因此,预计算:
const YourNumberType increment = (i? y : -y);
然后在你的循环中:
x += increment;
编辑:评论中关于如何生成代码的问题,如下所示:
#include <stdio.h>
void display( int x ) { printf( "%dn", x ); }
template< bool isSomething >
inline void advance( int& x, int y );
template<> inline void advance<true>( int& x, int y ) { x += y; }
template<> inline void advance<false>( int& x, int y ) { x -= y; }
template< bool isSomething >
void myFunc()
{
int x = 314;
int y = 271;
for( ;; )
{
advance< isSomething >( x, y ); // The nano-optimization.
display( x );
if( !( -10000 < x && x < 10000 ) ) { return; }
}
}
int main( int n, char*[] )
{
n > 1? myFunc<true>() : myFunc<false>();
}
例如,在Visual C++10.0中,这会生成两个版本的myFunc
,一个版本带有add
指令,另一个版本具有sub
指令。
干杯&hth。,
在现代流水线机器上,在性能真正重要的情况下,如果可能的话,您希望避免分支。当管道的前端碰到一个分支时,CPU会猜测要采用哪个分支,并根据该猜测让管道继续工作。如果猜测正确,一切都会好起来的。如果猜测错误,一切都不太好,尤其是如果你仍在使用英特尔的一款处理器,比如遭受管道膨胀的奔腾4。英特尔发现过多的流水线操作不是一件好事。
更现代的处理器仍然使用流水线(核心线的流水线长度约为14(,因此避免分支仍然是一件好事——当它重要的时候。当它不重要的时候,不要让你的代码变得丑陋、过早优化。
最好的做法是首先找出你的表演恶魔在哪里。几乎所有CPU使用率都是由代码库的1%的一小部分引起的,这并不罕见。优化99.9%不影响CPU使用的代码不会解决性能问题,但会对维护产生有害影响。
一旦找到了罪魁祸首代码,就可以进行优化,即使这样,也可能不会。当性能无关紧要时,不要进行优化。性能作为一个度量与几乎所有其他代码质量度量背道而驰。
所以,抛开肥皂盒不谈,让我们假设这一小段代码是性能的罪魁祸首。尝试两种方法并进行测试。尝试第三种你还没有想到的方法并进行测试。有时,性能最好的代码令人惊讶地不直观。想想达夫的装置。
如果i
在循环执行期间保持不变,而y
没有,则将if
移出循环。
所以。。。
your_loop {
y = ...;
if (i)
x += y;
else
x -= y;
}
请执行以下操作。。。。
if (i) {
your_loop {
y = ...;
x += y;
}
}
else {
your_loop {
y = ...;
x -= y;
}
}
顺便说一句,一个好的编译器会为你做优化,所以当你真正进行基准测试时,你可能看不到区别。
听起来你想避免分支和乘法。假设开关i
在您想要相加时被设置为所有1
位,大小与y
相同,在您想要相减时被设置成0
。然后:
x += (y & i) - (y & ~i)
还没有测试过,这只是给你一个大致的想法。请记住,这会使代码更难阅读,以换取效率的微小提高。
编辑:或者,正如bdonlan在评论中指出的那样,甚至可能减少。
我在评论中提出了我的建议进行测试,在一个简单的测试中,篡改比英特尔(R(至强(R(CPU L5520 2.27GHz上的分支选项更快,但在我的笔记本电脑英特尔酷睿双核上更慢。
如果您可以自由地给i
值0
(表示+(或~0
(表示-(,则这些语句等效:
// branching:
if ( i ) sum -= add; else sum += add;
sum += i?-add:add;
sum += (i?-1:1)*add;
// bit fiddling:
sum += (add^i)+(i&1);
sum += (add^i)+(!!i);
sum += (i&~add)-(i&add);
如上所述,根据CPU和使用的优化级别,一种方法可以以2倍的优势击败另一种方法。
结论是,和往常一样,基准测试是找出在特定情况下哪个更快的唯一方法。
- 有哪些有效的方法可以消除一组 100 万个字符串>重复数据?
- 在C++中初始化向量映射的最有效方法
- 将此布尔值传递给此函数的最有效方法是什么?
- 找到一种有效的方法,在 2 个巨大的缓冲区上执行 MAX,每字节字节
- 如何在工厂方法中返回指向基于基础操作系统的派生类的有效指针
- 比较C++中两个整数的最有效和最干净的方法是什么?
- 比较C++变量的最有效方法
- C++函子,有什么有效的方法吗?
- 在 c++ 中解决段树以外的范围查询的有效方法是什么?
- 存储变量的更有效方法是什么?
- 确保套装新鲜度的有效方法
- 当映射包含字符串向量作为值时,从值中获取键的有效方法
- 映射唯一值和重复值的有效方法.可以访问键或值的位置
- 在C++事务之间存储大量字符数据的有效方法
- 在unordered_multimap中精确迭代一次每个键的有效方法
- 证明两指针方法有效(对和)
- leetcode中的最大数字:有人能解释为什么这个方法有效吗
- C++ 用指针反向打印数组内容 - 为什么此方法有效
- Makefile:为什么这种自动生成先决条件的方法有效
- g++链接错误-解决方法有效的原因