所以,我正在制作一个Hack CPU模拟器,我想知道计算输出的最佳方法是什么。将输出计算压缩成一条不可读的线路比一次一步计算结果更有效吗?编译器是否优化它以使两个选项都正常?基本上,哪些更有效 -
这样:
word HackALU(word x, word y, bool zx, bool nx, bool zy, bool ny, bool f, bool no) { x = zx ? 0 : x; y = zy ? 0 : y; x = nx ? ~x : x; y = ny ? ~y : y; word result = f ? x + y : x & y; return no ? ~result : result; }
或者这个:
word HackALU(word x, word y, bool zx, bool nx, bool zy, bool ny, bool f, bool no) { return no ? ~(f ? ((nx ? ~(zx ? 0 : x) : (zx ? 0 : x)) + (ny ? ~(zy ? 0 : y) : (zy ? 0 : y))) : ((nx ? ~(zx ? 0 : x) : (zx ? 0 : x)) & (ny ? ~(zy ? 0 : y) : (zy ? 0 : y)))) : (f ? ((nx ? ~(zx ? 0 : x) : (zx ? 0 : x)) + (ny ? ~(zy ? 0 : y) : (zy ? 0 : y))) : ((nx ? ~(zx ? 0 : x) : (zx ? 0 : x)) & (ny ? ~(zy ? 0 : y) : (zy ? 0 : y)))); }
答案 0 :(得分:1)
一个好的现代编译器很可能会为两者生成相同的代码。
答案 1 :(得分:1)
逻辑变化会对代码的性能产生更大的影响,而不是临时的空白/存储。
例如,某些机器没有分支预测(例如PS3 SPU),在这种情况下,通过用数学运算替换分支,您的代码将明确更快
word HackALU(word x, word y, bool zx, bool nx, bool zy, bool ny, bool f, bool no)
{
x = (zx == 0) * x; // [0 or 1] * x;
y = (zy == 0) * y;
x -= (nx != 0) * 2 * x;
y -= (ny != 0) * 2 * x;
word result = (f != 0) * (x + y) + (f == 0) * (x & y);
return (no != 0) * ~result + (no == 0) * result;
}
答案 2 :(得分:0)
使用这个循环,我实际上显示顶级版本更快:
int n = 0; //optimization busting counter
clock_t start = clock();
for( word x=0; x<1000; ++x ) {
for( word y=0; y<1000; ++y ) {
for( int b = 0; b < 64; ++b ) {
n += HackALU(x,y,b&0x1,b&0x2,b&0x4,b&0x8,b&0x10,b&0x20);
} } }
clock_t end = clock();
printf("finished, elapsed ticks = %d, n = %d\n", end - start, n);
很明显,除非优化器非常好,否则顶级版本的指令会更少......我认为加快速度需要减少分支或确保它们准确预测。