Есть ли способ ускорить оценку следующего выражения?

Я профилировал свою программу, и она тратит 20% процессорного времени, в основном оценивая следующее выражение:

abs(x) > abs(y)

где x, y — переменные с плавающей запятой двойной точности.

Есть ли способ реорганизовать выражение в более быстрый вариант?

Следующая строка (вызывается в двух разных местах) занимает около 10% процессорного времени в каждой строке:

(Это фрагмент из функции Image_3 :: TestGradientAtPoint)

       if (abs(maxx[ch]) < abs(a)) maxx[ch] = a;
01187AC9  mov         eax,dword ptr [ch]
01187ACC  sub         esp,8
01187ACF  fld         qword ptr [ebp+eax*8-68h]
01187AD3  fstp        qword ptr [esp]
01187AD6  call        abs (11305F9h)
01187ADB  fld         qword ptr [ebp-70h]
01187ADE  fstp        qword ptr [esp]
01187AE1  fstp        qword ptr [ebp-0F8h]
01187AE7  call        abs (11305F9h)
01187AEC  add         esp,8
01187AEF  fcomp       qword ptr [ebp-0F8h]
01187AF5  fnstsw      ax
01187AF7  test        ah,41h
01187AFA  jne         Image_3::TestGradientAtPoint+176h (1187B06h)
01187AFC  mov         eax,dword ptr [ch]
01187AFF  fld         qword ptr [ebp-70h]
01187B02  fstp        qword ptr [ebp+eax*8-68h]

Профилировщик заявил, что вызов abs () занял 20% процессорного времени.
Я вызываю метод порядка 10 ^ 8 итераций — я работаю с большими изображениями.

редактировать

Я забыл это сказать, но код работает в режиме отладки, и мне нужно немного его оптимизировать, потому что я все еще хочу использовать отладчик MSVC в разумные сроки.

1

Решение

Это не может быть быстрее, но если арифметические выражения вычисляются быстрее:

if ((x - y) * (-x - y) < 0)
// then abs(x) > abs(y)

Я полагаю, что это фиксирует число выражений в 3 (арифметическое выражение 2 и сравнение с нулем), а не в выражении 3 из метода abs (каждый abs проверяет наличие отрицательного значения, инвертирует знак, в противном случае просто возвращает значение, затем сравнивает каждый abs)

РЕДАКТИРОВАТЬ:

Как и сказал Андре, вы всегда можете явным образом выровнять поплавки. Имеет гораздо больше смысла в ретроспективе.

if (x * x > y * y)
// then abs(x) > abs(y)

Так как (х-у) (- х-у) = у ^ 2-х ^ 2

6

Другие решения

Скажите вашему компилятору для оптимизации. В GCC или Clang вы делаете это с помощью -O2 или же -O3 флаги — последний более агрессивен. В MSVC вы можете использовать /O2 или же /Ox флаги (IIRC; я редко использую этот компилятор). Вы не можете ожидать, что 100000000 итераций будут выполняться быстро без включенных оптимизаций.

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

5

Хорошо, если порядок maxx[] это не важно, вы могли бы отсортировать его, и я думаю, что это будет быстрее.

Другое дело, что если «а» это то же самое для всех maxx[] ты мог бы сделать a= abs(a); а затем просто сравнить с напрямую.

Мне нужно увидеть больше кода, чтобы попытаться помочь вам больше.

4

Первое, что нужно проверить, это то, что вы на самом деле включаете оптимизацию. Если нет, возможно, ваш компилятор не вставляет вызов, что приводит к достаточным накладным расходам, чтобы вы это заметили.

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

Так что вам нужно учитывать такие вещи, как:

  • Вы заботитесь об исходных отрицательных числах или можете предварительно отфильтровать данные absесли это?
  • Вы заботитесь о заказе? Можете ли вы отсортировать данные, чтобы улучшить свой алгоритм
  • Вы вычисляете abs неизменного значения много раз в цикле?
2

Это не может быть быстрее, но другая логическая версия будет:

// logical replacement for abs(x) > abs(y)
x >= 0 ?
y >= 0 && x > y :
y <= 0 && x < y ;

Так как он использует только компараторы и ответвления, может Быстрее, но без гарантий …

Если нет, попробуйте использовать fabs вместо этого, поскольку он предназначен для чисел с плавающей точкой.

2
По вопросам рекламы [email protected]