Насколько медленной является арифметика NaN в Intel x64 FPU? - PullRequest
5 голосов
/ 31 августа 2010

Существует множество подсказок и утверждений, что арифметика с NaN может быть «медленной» в аппаратных FPU. В частности, в современном x64 FPU, например, на Nehalem i7, это все еще верно? Умножаются ли FPU на одну и ту же скорость независимо от значений операндов?

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

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

Я буду делать это из CLR, если это будет иметь значение для аромата генерируемых NaN.

1 Ответ

6 голосов
/ 31 августа 2010

Для чего стоит использовать инструкцию SSE mulsd с NaN почти так же быстро, как и с константой 4.0 (выбранной при броске кубиков, гарантированно случайным).

Этот код:

for (unsigned i = 0; i < 2000000000; i++)
{
    double j = doubleValue * i;
}

генерирует этот машинный код (внутри цикла) с помощью clang (я полагаю, что виртуальная машина .NET использует инструкции SSE, когда это возможно):

movsd     -16(%rbp), %xmm0    ; gets the constant (NaN or 4.0) into xmm0
movl      -20(%rbp), %eax     ; puts i into a register
cvtsi2sdq %rax, %xmm1         ; converts i to a double and puts it in xmm1
mulsd     %xmm0, %xmm1        ; multiplies xmm0 (the constant) with xmm1 (i)
movsd     %xmm1, -32(%rbp)    ; puts the result somewhere on the stack

И с двумя миллиардами итераций версия NaN (как определено макросом C NAN из <math.h>) заняла примерно 0,017 меньше секунд для выполнения на моем i7. Разница, вероятно, была вызвана планировщиком задач.

Честно говоря, они такие же быстрые.

...