在C#中,使用位运算符而不是纯整数求和是否能显著提高性能?

7

我几周前开始学习C#,现在需要构建一个"位集合"标志来处理算法中的不同情况。因此,我有两个选项:

    enum RelativePositioning
    {
        LEFT = 0,
        RIGHT = 1,
        BOTTOM  = 2,
        TOP = 3,
        FRONT = 4,
        BACK = 5
    }

    pos = ((eye.X < minCorner.X ? 1 : 0) << (int) RelativePositioning.LEFT)
        + ((eye.X > maxCorner.X ? 1 : 0) << (int) RelativePositioning.RIGHT)
        + ((eye.Y < minCorner.Y ? 1 : 0) << (int) RelativePositioning.BOTTOM)
        + ((eye.Y > maxCorner.Y ? 1 : 0) << (int) RelativePositioning.TOP)
        + ((eye.Z < minCorner.Z ? 1 : 0) << (int) RelativePositioning.FRONT)
        + ((eye.Z > maxCorner.Z ? 1 : 0) << (int) RelativePositioning.BACK);

或者:

    enum RelativePositioning
    {
        LEFT = 1,
        RIGHT = 2,
        BOTTOM  = 4,
        TOP = 8,
        FRONT = 16,
        BACK = 32
    }

    if (eye.X < minCorner.X) { pos += (int) RelativePositioning.LEFT;   }
    if (eye.X > maxCorner.X) { pos += (int) RelativePositioning.RIGHT;  }
    if (eye.Y < minCorner.Y) { pos += (int) RelativePositioning.BOTTOM; }
    if (eye.Y > maxCorner.Y) { pos += (int) RelativePositioning.TOP;    }
    if (eye.Z > maxCorner.Z) { pos += (int) RelativePositioning.FRONT;  }
    if (eye.Z < minCorner.Z) { pos += (int) RelativePositioning.BACK;   }

我本可以使用 ((eye.X > maxCorner.X) << 1) 这样的表达式,但是C#不允许将bool类型隐式转换为int类型,三目运算符则相似度更高。我的问题是:第一种方式是否比第二种方式性能更好?

谢谢
Tommaso


8
在执行微小优化之前,请进行基准测试。 - Mitch Wheat
4
"我们应该忘记小细节,这大约占到了97%的时间:过早优化是万恶之源。" —— Donald Knuth - Cagdas
1
你为什么不使用带有Flag属性的枚举类型? - Phil Gan
2
@ Cagdas:我将在非常短的时间内(尽可能短)重复这个过程至少10K次,因此我想任何小的优化都可以。此外,我正在进行优化,这种改进不是过早的,而是在工作代码中实现的。 - tunnuz
1
既然我们正在进行微观优化,那么在你的第二个示例中使用"|="而不是"+="怎么样(但要进行性能分析!),并添加一些“else”(当x < min时,它可能不会大于max,因此在那里使用“else if”)。 - Hans Kesting
显示剩余3条评论
3个回答

8
你应该为你的枚举类型使用 Flags 属性。这样它看起来会像这样:
[Flags]
public enum RelativePositionings
{
    None = 0,
    Left = 1,
    Right = 2,
    Bottom  = 4,
    Top = 8,
    Front = 16,
    Back = 32
}

使用这个工具你可以做以下事情:

var position = RelativePositionings.Left | RelativePositionings.Front;

并通过以下方式检查每个状态:

if(position.HasFlag(RelativePositioning.Left))
{
    //To do: if left bit is set?
}

5
内联 if 运算符 (?, :) 生成的 IL 几乎与第二个示例中的标准 if 列表相同。你只会在这里看到特定操作处理器将要执行的区别,而我敢打赌 ADDSHL 更快。
既然你无论如何都要添加结果,我建议选择第二个示例(这样更容易阅读)。 编辑
我刚刚检查了两个示例的 IL,发现与我上面说的不一样。
第一个示例生成的 IL 要少得多(少了34行),因此你需要运行性能测试来真正确定它是否更快。

0

显著更快?不是。稍微快一点?是的。


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