在 C# 中使用按位运算符而不是普通的 int 总和会带来显着的性能提升吗?

发布于 2024-09-01 18:45:11 字数 1554 浏览 10 评论 0原文

几周前我开始使用 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 的隐式转换三元运算符非常相似。我现在的问题是:使用第一个版本比第二个版本有任何性能改进吗?

谢谢
托马索

I started working with C# a few weeks ago and I'm now in a situation where I need to build up a "bit set" flag to handle different cases in an algorithm. I have thus two options:

    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);

Or:

    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;   }

I could have used something as ((eye.X > maxCorner.X) << 1) but C# does not allow implicit casting from bool to int and the ternary operator was similar enough. My question now is: is there any performance improvement in using the first version over the second?

Thank you
Tommaso

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

金兰素衣 2024-09-08 18:45:11

您绝对应该为枚举使用 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?
}

You should definitely use the Flags attribute for your enum. That way it would look something like that:

[Flags]
public enum RelativePositionings
{
    None = 0,
    Left = 1,
    Right = 2,
    Bottom  = 4,
    Top = 8,
    Front = 16,
    Back = 32
}

With this you can do such things like:

var position = RelativePositionings.Left | RelativePositionings.Front;

and check for each state by:

if(position.HasFlag(RelativePositioning.Left))
{
    //To do: if left bit is set?
}
成熟稳重的好男人 2024-09-08 18:45:11

内联 if 运算符(?, :)将生成与标准 if 列表几乎相同的 IL。第二个例子。您在这里看到的唯一区别是处理器将执行的特定操作,我敢打赌 ADDSHL 更快。​​
由于无论如何您都会添加结果,因此我会选择第二个示例(而且它更易于阅读)。

编辑
我刚刚检查了两个示例的 IL,它与我上面所说的相悖。
第一个示例生成的 IL 少得多(少了 34 行),因此您必须运行性能测试才能真正确定它是否也更快。

The inline if operator (?, :) will generate nearly the same IL as the standard if list in the second example. The only difference you will see here are the particular operations the processor will be doing, and I can bet that ADD is quicker than SHL.
Since you're going to be adding the results anyway, I would opt for the second example (plus it makes it far easier to read).

EDIT
I just checked the IL of both examples, and it goes against what I have said above.
The first example generates far less IL (34 lines less) so you'll have to run a performance test to really determine if it is faster too.

暖伴 2024-09-08 18:45:11

明显更快?不。稍微快一点?一点点。

Significantly faster? no. Slightly faster? A little bit.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文