title: Adding two vector in assembly x86_64 with AVX2 plus technical clarifications
body: <p>What am I doing wrong here? I'm getting 4 zeros instead of:</p>
  
  <pre><code>2
  4
  6
  8
  </code></pre>
  
  <p>I would also love to modify my .asm function in order to run through longer vectors 'cause to semplify here I've just used a vector with four elements so that I can sum that vector without a loop with SIMD 256 bit registers.</p>
  
  <h2>.cpp</h2>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;chrono&gt;
  
  extern "C" double *addVec(double *C, double *A, double *B, size_t &amp;N);
  
  int main()
  {
      size_t N = 1 &lt;&lt; 2;
      size_t reductions = N / 4;
  
      double *A = (double*)_aligned_malloc(N*sizeof(double), 32);
      double *B = (double*)_aligned_malloc(N*sizeof(double), 32);
      double *C = (double*)_aligned_malloc(N*sizeof(double), 32);
  
      for (size_t i = 0; i &lt; N; i++)
      {
          A[i] = double(i + 1);
          B[i] = double(i + 1);
      }
  
      auto start = std::chrono::high_resolution_clock::now();
  
          double *out = addVec(C, A, B, reductions);
  
      auto finish = std::chrono::high_resolution_clock::now();
  
      for (size_t i = 0; i &lt; N; i++)
      {
          std::cout &lt;&lt; out[i] &lt;&lt; std::endl;
      }
  
      std::cout &lt;&lt; "\n\n";
  
      std::cout &lt;&lt; std::chrono::duration_cast&lt;std::chrono::nanoseconds&gt;(finish - start).count() &lt;&lt; " ns\n";
  
      std::cin.get();
  
      _aligned_free(A);
      _aligned_free(B);
      _aligned_free(C);
  
      return 0;
  }
  </code></pre>
  
  <h2>.asm</h2>
  
  <pre><code>.data
  ; C -&gt; RCX
  ; A -&gt; RDX
  ; B -&gt; r8
  ; N -&gt; r9
  .code
      addVec proc
          ;xor rbx, rbx
          align 16
          ;aIn:
              vmovapd ymm0, ymmword ptr [rdx]
              ;vmovapd ymm1, ymmword ptr [rdx + rbx + 4]
              vmovapd ymm2, ymmword ptr [r8]
              ;vmovapd ymm3, ymmword ptr [r8 + rbx + 4]
  
              vaddpd ymm0, ymm2, ymm3
  
              vmovapd ymmword ptr [rcx], ymm3
          ;inc rbx
          ;cmp rbx, qword ptr [r9]
          ;jl aIn
          mov rax, rcx    ; return the address of the output vector
      ret
      addVec endp
  end
  </code></pre>
  
  <p>Also I would like to have some other clarifications:</p>
  
  <ol>
  <li>Are there eight 256 bit registers (ymm0-ymm7) for each core o my CPU or there are eight in total?</li>
  <li>All the other register like rax, rbx etc... are in total or for each core?</li>
  <li>Since I can handle 4 double per cycle just with SIMD coprocessor and one core, can I execute another instruction per cycle with the rest of my CPU? So for example can I add 5 double per cycle with one core? (4 with SIMD + 1)</li>
  <li><p>What if I do something like the following without putting a loop inside my assembly function?:</p>
  
  <p><code>#pragma openmp parallel for</code></p>
  
  <p><code>for (size_t i = 0; i &lt; reductions; i++)</code></p>
  
  <p><code>addVec(C + i, A + i, B + i)</code></p>
  
  <p>is this going to fork coreNumber + hyperThreading threads and each of them perform a SIMD add on four double? So in total 4 * coreNumber double for each cycle? I can't add the hyperThreading here right?</p></li>
  </ol>
  
  <hr>
  
  <p>Update can I do this?:</p>
  
  <pre><code>.data
  ;// C -&gt; RCX
  ;// A -&gt; RDX
  ;// B -&gt; r8
  .code
      addVec proc
          ; One cycle 8 micro-op
              vmovapd ymm0, ymmword ptr [rdx]     ; 1 port
              vmovapd ymm1, ymmword ptr [rdx + 32]; 1 port
              vmovapd ymm2, ymmword ptr [r8]      ; 1 port
              vmovapd ymm3, ymmword ptr [r8 + 32] ; 1 port
              vfmadd231pd ymm0, ymm2, ymm4        ; 1 port
              vfmadd231pd ymm1, ymm3, ymm4        ; 1 port
              vmovapd ymmword ptr [rcx], ymm0     ; 1 port
              vmovapd ymmword ptr [rcx + 32], ymm1; 1 port
  
          ; Return the address of the output vector
          mov rax, rcx                            ; 1 port ?
      ret
      addVec endp
  end
  </code></pre>
  
  <p>Or just this 'cause I would exceed the six ports that you told me?</p>
  
  <pre><code>.data
  ;// C -&gt; RCX
  ;// A -&gt; RDX
  ;// B -&gt; r8
  .code
      addVec proc
          ;align 16
          ; One cycle 5 micro-op ?
          vmovapd ymm0, ymmword ptr [rdx]     ; 1 port
          vmovapd ymm1, ymmword ptr [r8]      ; 1 port
          vfmadd231pd ymm0, ymm1, ymm2        ; 1 port
          vmovapd ymmword ptr [rcx], ymm0     ; 1 port
  
          ; Return the address of the output vector
          mov rax, rcx                        ; 1 port ?
      ret
      addVec endp
  end
  </code></pre>