Оптимальное (временная парадигма) решение для проверки переменной внутри границы - PullRequest
0 голосов
/ 21 мая 2010

Извините, если вопрос очень наивный.
Я должен буду проверить условие ниже в моем коде

0
т.е. код похож на if(x > 0 && x < y)

Основная проблема на системном уровне - в настоящее время для каждого звонка (терминология домена Telecom) мой существующий код срабатывает (много раз). Таким образом, производительность очень важна. Теперь мне нужно добавить проверку для проверки границ (во многих местах - но разные сравнения границ в каждом месте).

При очень нормальном уровне кодирования приведенное выше сравнение выглядело бы очень наивно без каких-либо проблем. Однако при добавлении в мой модуль статистики (который многократно опускается) производительность снижается.

Итак, я хотел бы знать, как лучше всего справиться с описанным выше сценарием (своего рода оптимальный способ проверки пределов). Как, например, если сравнение битов работает лучше, чем обычное сравнение, или сравнение может быть выполнено за более короткий промежуток времени?

Другая информация

x - целое число без знака (которое должно быть проверено, чтобы быть больше 0 и меньше y). у - целое число без знака.
у неконстантный и меняется для каждого сравнения.
Здесь время - это ограничение по сравнению с пространством.
Язык - C ++.

Теперь, позже, если мне понадобится изменить атрибут y на число с плавающей запятой / double, будет ли другой способ оптимизировать проверку (т. Е. Будет ли предложенный оптимальный метод для целых чисел станет неоптимальным решением, когда y будет заменен на float /double).

Заранее спасибо за любой вклад.


PS: используется ОС SUSE 10 64-битная x64_64, AIX 5.3 64-битная, HP UX 11.1 A 64.

Ответы [ 3 ]

2 голосов
/ 21 мая 2010

Как всегда, сначала профиль, потом оптимизируй. Но, учитывая, что это на самом деле проблема, это может быть на что посмотреть:

  • «Без знака и больше нуля» - это то же самое, что и «не равно нулю», что обычно примерно так же быстро, как и при сравнении. Таким образом, первая оптимизация должна была бы сделать x != 0 && x < y.

  • Удостоверьтесь, что вы проводите сравнение, которое, скорее всего, провалит первое, чтобы максимизировать выигрыш от короткого замыкания.

  • Если возможно, используйте директивы компилятора, чтобы сообщить компилятору о наиболее вероятном пути к коду. Это оптимизирует предварительную выборку команд и т. Д. для GCC посмотрите что-то вроде this, сделанное в ядре .

Я не думаю, что уловки с вычитанием и сравнением с нулем и т. Д. Принесут какую-либо выгоду. Если это самый эффективный способ сравнения меньше, вы можете быть уверены, что ваш компилятор уже знает об этом.

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

Вам, вероятно, не нужно менять y на число с плавающей или двойной; Вы должны стараться оставаться в целых числах столько, сколько сможете. Вместо того, чтобы представлять y как секунды, попробуйте микросекунды или миллисекунды (в зависимости от необходимого разрешения).

В любом случае, я подозреваю, что вы можете изменить

if (x > 0 && x < y)
   ;

до

if ((unsigned int)x < (unsigned int)y)
   ;

но это, вероятно, не собирается ничего ускорять. Проверка на ноль часто является одной или двумя инструкциями (в зависимости от ISA), поэтому считывание из памяти, безусловно, является здесь узким местом.

После того, как вы профилировали свой код и определили, что на самом деле именно здесь возникают проблемы с производительностью, вы можете заняться настройкой предиктора ветвления, поскольку это может быть потрачено много времени, если его регулярно неправильно прогнозировать. Разные компиляторы делают это по-разному, но у некоторых есть свойство типа __expect(x < 0);, которое скажет предиктору предположить, что это обычно так.

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

Это исключает сравнение и переход за счет двух добавлений; должно быть быстрее:

(x-1) < (y-1)

Это работает, пока y гарантированно ненулевой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...