Есть ли существенное улучшение производительности за счет использования побитовых операторов вместо простых чисел int в C #? - PullRequest
7 голосов
/ 17 мая 2010

Я начал работать с 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, и троичный оператор был достаточно похож. Мой вопрос сейчас: есть ли улучшение производительности при использовании первой версии по сравнению со второй?

Спасибо.
Томмазо

Ответы [ 3 ]

8 голосов
/ 17 мая 2010

Вы обязательно должны использовать атрибут 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 голосов
/ 17 мая 2010

Оператор inline if (?, :) сгенерирует почти тот же IL, что и стандартный список if во втором примере. Единственное отличие, которое вы увидите здесь, это конкретные операции, которые будет выполнять процессор, и я могу поспорить, что ADD быстрее, чем SHL.
Так как вы все равно будете добавлять результаты, я бы выбрал второй пример (плюс он намного удобнее для чтения).

EDIT
Я только что проверил IL обоих примеров, и это идет вразрез с тем, что я сказал выше.
В первом примере генерируется намного меньше IL (на 34 строки), поэтому вам придется запустить тест производительности, чтобы действительно определить, быстрее ли он.

0 голосов
/ 17 мая 2010

Значительно быстрее? нет. Чуть быстрее? Немного.

...