Можно / эффективно ли ввести в работу исключение fpu или inf?

0

У меня такой код

петля 10 M:

 if( fz != 0.0)     
 { 
  fhx += hx/fz; 
 } 

это называется 10 М раз в цикле, нужно быть очень быстрым - я просто должен поймать случай, когда fz не равен нулю, а не делать div с нулевой ошибкой, но это очень редкий случай, действительно, в 10-мегабитных случаях это должно быть ноль, я не знаю один, два или более

могу ли я каким-то образом избавиться от этого 10M ifs и использовать "nan/inf" или, может быть, поймать исключение и продолжить? (если fz равно нулю, мне нужно fhx + = 0.0, я не имею в виду ничего, что только можно продолжить? Возможно ли/эффективно помещать исключение fpu или inf в работу?

(Im, использующий c++/mingw32)

  • 1
    Вы действительно работаете с кодом FPU? С SSE вы можете легко сравнивать и маскировать (вместо ответвления).
  • 0
    Насколько предсказуема ветка и как часто она может привести к пропуску деления? Использование исключения очень медленно, если только оно не происходит приблизительно никогда.
Показать ещё 7 комментариев
Теги:
optimization
x86
sse
fpu

1 ответ

1
Лучший ответ

Вы можете, но это, вероятно, не так уж полезно. Маскировка не будет полезна ни при каких обстоятельствах.

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

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

Пропускная способность этого деления составляет 1 на 14 циклов в любом случае (на Хасуэлл - хуже на других μarchs), если только fz является особенно "приятным", и даже тогда он 1 на 8 циклов (опять же на Хасуэле). На Core2 это было больше похоже на 19 и 5, на P4 оно больше напоминало (в типичном режиме P4) одно деление на 71 цикл независимо от того, что.

Хорошо предсказанная ветвь и сравнение просто исчезают в этом. На моем 4770K разница между тем, что сравнение и ветвь там или не исчезла в шуме (возможно, если я буду запускать ее достаточно времени, я в конечном итоге получу статистически значимое различие, но она будет крошечной), причем оба они случайно выигрывают наполовину. Код, который я использовал для этого теста, был

global bench
proc_frame bench
    push r11
[endprolog]
    xor ecx, ecx
    mov rax, rcx
    mov ecx, -10000000
    vxorps xmm1, xmm1
    vxorps xmm2, xmm2
    vmovapd xmm3, [rel doubleone]
_bench_loop:
    imul eax, ecx, -0xAAAAAAAB  ; distribute zeroes somewhat randomly
    shr eax, 1                  ; increase to make more zeroes
    vxorps xmm0, xmm0
    vcvtsi2sd xmm0, eax
    vcomisd xmm0, xmm1          ; #
    jz _skip                    ; #
    vdivsd xmm0, xmm3, xmm0
    vaddsd xmm2, xmm0
_skip:
    add ecx, 1
    jnz _bench_loop
    vmovapd xmm0, xmm2
    pop r11
    ret
endproc_frame

Другая функция была такой же, но с двумя строками, отмеченными # комментарием.

Версия, которая в конечном счете последовательно выигрывает, когда число нулей увеличивается, является тем, у которого есть ветка, что указывает на то, что деление на ноль значительно медленнее, чем неверное предсказание ветки. Это, даже не используя механизм исключения для создания видимого для программиста видимого исключения, это просто из-за стоимости запущенной микрозаписей "странного случая". Но у вас нет такого количества нулей,

TL; DR нет никакой разницы.

  • 0
    Интересно, у меня также есть 3 машины, и это p4 core2 и haswell; o очень интересный ответ - вот пример экрана dropbox.com/s/f5bg08d1mxzht40/… Мне нужно, если для каждого пикселя хотя бы случаи, когда z == 0.0000000, вероятно, очень редко, с другой стороны, я беру x / z mul его по некоторому значению cat в int и это с & 1023 и использую его как индекс поиска текстуры - около экватора я, вероятно, получил значения больше MAX_INT, поэтому приведение его к int уже дает неправильные значения, но это случайно
  • 0
    не имеет большого значения, возможно, если я не поймаю исключение, но приведу ste inf к int, тогда использовать его будет без разницы - передача на inf будет медленнее, чем if-cecking?
Показать ещё 9 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню