寻找其他节点的最快方法

3

我有一个三角形类,其中包含指向节点(n0,n1,n2)的指针。我还有一个方法,当传入两个节点指针(a,b)时返回“其他”节点。当前实现如下:

if ( n0 == a && n1 == b )
{
    return n2;
}
else if ( n0 == b && n1 == a )
{
    return n2;
}
else if ( n1 == a && n2 == b )
{
    return n0;
}
else if ( n1 == b && n2 == a )
{
    return n0;
}
else if ( n0 == a && n2 == b )
{
    return n1;
}
else if ( n0 == b && n2 == a )
{
    return n1;
}
else
{
    assert( 0 );
}
return NULL;

这个方法虽然可行,但可能不是最好的。在进行性能分析时,我的程序实际上会花费一些时间在这个例程中,因此值得花一些时间进行优化。然而,我对编译器将要执行的优化不是很熟悉,所以我不确定这是否是多余的。

节点没有特定的顺序,因此平均而言,它将执行3.5个复合比较。

另一种方法是:

if ( n0 == a )
{
    if ( n1 == b )
    {
        return n2;
    }
    else if ( n2 == b )
    {
        return n1;
    }
    return NULL;
}
else if ( n1 == a )
{
    if ( n0 == b )
    {
        return n2;
    }
    else if ( n2 == b )
    {
        return n0;
    }
    return NULL;
}
else if ( n2 == a ) // Theoretically redundant.  Kept for safety.
{
    if ( n0 == b )
    {
        return n1;
    }
    else if ( n1 == b )
    {
        return n0;
    }
    return NULL;
}
return NULL;

这将平均需要3.5次简单比较。这样做会更快吗,还是编译器会让它们变得相同?
有没有更快的方法?
我知道我可以消除冗余的if语句。在第一种情况下,可以将平均值降至3.33个复合比较,而在第二种情况下,它将平均降至3.0个简单比较。
我可以消除所有else语句,因为每个真实的代码块都包含一个返回。然而,我真的觉得编译器应该足够聪明,能够自己处理任何收益。

“这样会更快吗” - 对其进行分析并找出答案。 - Remy Lebeau
你的代码似乎可以工作。对于想要进行优化的可工作代码,有一个适当的网站 - Fureeish
你的两个代码示例都考虑到了a和/或b可能根本不在节点中的情况。这是必须支持的真实可能性吗?还是ab保证始终在节点中?如果你能提供这种保证,那么你就可以减少一半的比较次数。 - Remy Lebeau
@Fureeish 抱歉在错误的地方提问。 - Rob McDonald
不,我认识到这是可能的失败。但在我的应用程序中实践中,我们实际上并没有检查从此例程返回的 NULL -- 而且代码已经运行了约 12 年,所以没有进行完全审核,看起来我们从未返回 NULL。 - Rob McDonald
显示剩余2条评论
1个回答

8

任何东西与自身进行异或运算的结果都是零,因此如果你已知其中两个数,可以通过计算 n0 ^ n1 ^ n2 ^ a ^ b 来得到第三个数。虽然这种方法需要解释说明,但如果速度很重要,那么这几乎肯定是最快的选择。


通过适当的转换,它似乎可以工作:return (Node *) ((uintptr_t) n0 ^ (uintptr_t) n1 ^ (uintptr_t) n2 ^ (uintptr_t) a ^ (uintptr_t) b);。这似乎很难被击败。 - Rob McDonald
1
假设ab都是指向正在被检查的三角形内部节点的指针。如果它们是指向外部节点的指针,则此方法将失败。 - Remy Lebeau
虽然这是对这个问题最好的回答,但它仍然没有回答稍微更一般的问题——复合条件语句是否比简单条件语句需要更多的时间?手动展开代码以达到没有重复检查的简单条件语句是否值得? - Rob McDonald

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接