2015-04-09 2 views
1

Поскольку операция fpu очень дорогостоящая, я бы хотел использовать операции fpu, насколько это возможно. Между тем, мне интересно, какие операции в переменной float будут учитываться как операция, которую использует fpu?Является ли задание с плавающей точкой считаться с использованием fpu?

Например, следующий код будет включать блок fpu?

struct my_float_struct { 
    int f; 
} g; 

void func(float a) 
{ 
    g.f = a; 
} 

вызвало бы func вызовет ленивый переключатель контекста FPU?

+0

Наверное, нет , но это зависит от аппаратного обеспечения. – Barmar

+0

Я не верю, что операция плавания доступна в ядре –

+1

Это зависит. Если 'g' был сохранен в регистре FPU, то, очевидно, будет использоваться FPU. –

ответ

0

В ядре вы не должны использовать float вообще (используйте lookup tables и умножайтесь на коэффициенты, чтобы сохранить точность на операциях деления). В пользовательском пространстве все операции с типом float на RHS приведут к использованию инструкции FPU. Если у вас есть 2 целых числа на RHS, но присваивание результата float (на LHS) - вы закончите с целыми операциями, но также с литьем в инструкцию по плаванию (например, cvtsi2ss).

На самом деле очень легко ответить на ваш вопрос, просто глядя на дизассемблирование для соответствующего кода на языке C.

код C (сборка с gcc -Wall -O0 -g main.c):

int main(void) 
{ 
    volatile float f1, f2; 
    volatile int i; 

    f1 = i * 356; 
    f2 = f1 * f2; 

    return 0; 
} 

Разберите (с использованием objdump -DS a.out):

int main(void) 
{ 
    4004b6:  55      push %rbp 
    4004b7:  48 89 e5    mov %rsp,%rbp 
     volatile float f1, f2; 
     volatile int i; 

     f1 = i * 356; 
    4004ba:  8b 45 f4    mov -0xc(%rbp),%eax 
    4004bd:  69 c0 64 01 00 00  imul $0x164,%eax,%eax 
    4004c3:  66 0f ef d2    pxor %xmm2,%xmm2 
    4004c7:  f3 0f 2a d0    cvtsi2ss %eax,%xmm2 
    4004cb:  66 0f 7e d0    movd %xmm2,%eax 
    4004cf:  89 45 fc    mov %eax,-0x4(%rbp) 
     f2 = f1 * f2; 
    4004d2:  f3 0f 10 4d fc   movss -0x4(%rbp),%xmm1 
    4004d7:  f3 0f 10 45 f8   movss -0x8(%rbp),%xmm0 
    4004dc:  f3 0f 59 c8    mulss %xmm0,%xmm1 
    4004e0:  66 0f 7e c8    movd %xmm1,%eax 
    4004e4:  89 45 f8    mov %eax,-0x8(%rbp) 

     return 0; 
    4004e7:  b8 00 00 00 00   mov $0x0,%eax 
} 

Здесь вы можете увидеть, что:

  • при умножении числа на целое число , но присваивая результат float, он приводит к команде imul (целочисленное умножение), но также и для команды cvtsi2ss (преобразование в float).
  • при умножении 2 поплавков, это приводит к mulss инструкции, которая поплавок множительной

В принципе вы можете увидеть сразу, если FPU участвует инструкция работает на регистрах FPU, как %xmm0, %xmm1 и т.д.

Смежные вопросы