Две очень похожие функции с участием sin () демонстрируют совершенно разную производительность - почему?

Рассмотрим следующие две программы, которые выполняют одни и те же вычисления двумя различными способами:

// v1.c
#include 
#include 
int main(void) {
   int i, j;
   int nbr_values = 8192;
   int n_iter = 100000;
   float x;
   for (j = 0; j < nbr_values; j++) {
      x = 1;
      for (i = 0; i < n_iter; i++)
         x = sin(x);
   }
   printf("%f\n", x);
   return 0;
}

а также

// v2.c
#include 
#include 
int main(void) {
   int i, j;
   int nbr_values = 8192;
   int n_iter = 100000;
   float x[nbr_values];
   for (i = 0; i < nbr_values; ++i) {
      x[i] = 1;
   }
   for (i = 0; i < n_iter; i++) {
      for (j = 0; j < nbr_values; ++j) {
         x[j] = sin(x[j]);
      }
   }
   printf("%f\n", x[0]);
   return 0;
}

Когда я компилирую их, используя gcc 4.7.2 с-O3 -ffast-math и запустить на коробке Sandy Bridge, вторая программа в два раза быстрее, чем первая.

Это почему?

Одним из подозрений является зависимость данных между последовательными итерациямиi зациклитьсяv1, Тем не менее, я неЯ не вижу полного объяснения.

(Вопрос вдохновленПочему мой пример с python / numpy быстрее, чем реализация на чистом C?)

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

Вот сгенерированная сборка для:v1

        movl    $8192, %ebp
        pushq   %rbx
LCFI1:
        subq    $8, %rsp
LCFI2:
        .align 4
L2:
        movl    $100000, %ebx
        movss   LC0(%rip), %xmm0
        jmp     L5
        .align 4
L3:
        call    _sinf
L5:
        subl    $1, %ebx
        jne     L3
        subl    $1, %ebp
        .p2align 4,,2
        jne     L2

и для :v2

        movl    $100000, %r14d
        .align 4
L8:
        xorl    %ebx, %ebx
        .align 4
L9:
        movss   (%r12,%rbx), %xmm0
        call    _sinf
        movss   %xmm0, (%r12,%rbx)
        addq    $4, %rbx
        cmpq    $32768, %rbx
        jne     L9
        subl    $1, %r14d
        jne     L8

Ответы на вопрос(2)

Ваш ответ на вопрос