---
# System prepended metadata

title: SIMD Programming

---

# SIMD Programming
## Q1-1
<font color="#f00">Q: Does the vector utilization increase, decrease or stay the same as VECTOR_WIDTH changes? Why?</font>
A:
Vector width=2
![](https://hackmd.io/_uploads/BJF1cIGfa.png)



Vector width=4
![](https://hackmd.io/_uploads/SJAcKIff6.png)


Vector width=8
![](https://hackmd.io/_uploads/SJ0uKUMfT.png)


Vector width=16
![](https://hackmd.io/_uploads/r18XK8zz6.png)


當Vector width變大時，Vector Utilization的值在變小。我認為可能的原因是當Vector width變大時，N%Vector width的值就有較大機會變比較大，而導致很多Lane沒有被使用。
另外，在指數運算的時候，也會因為某些exponent已經算到0，但其他lane還沒算到0，而導致未使用lane的數量越來越多，進而導致Vector Utilization的值變小。



<font color="#f00">Q: Fix the code to make sure it uses aligned moves for the best performance.</font>
A: AVX2指令集為256bits(32bytes)，所以如果要讓vmovaps出現比vmovups多的話，就要達到align AVX2指令集的效果，也就是說要讓編譯器知道要align 32bytes，如以下程式碼。
![](https://hackmd.io/_uploads/HJshTR0-6.png)圖1

## Q2-2
<font color="#f00">Q: What speedup does the vectorized code achieve over the unvectorized code? What additional speedup does using -mavx2 give (AVX2=1 in the Makefile)? You may wish to run this experiment several times and take median elapsed times; you can report answers to the nearest 100% (e.g., 2×, 3×, etc). What can you infer about the bit width of the default vector registers on the PP machines? What about the bit width of the AVX2 vector registers.</font>
A:在test1:
 ![](https://hackmd.io/_uploads/H1d2mxgz6.png)圖2
 vectorized code 和  unvectorized code的時間分別為約2.63s(圖3)及8.29s(圖4)，以5次做平均(圖2)。


 ![](https://hackmd.io/_uploads/r1PX7blG6.png)圖3

 ![](https://hackmd.io/_uploads/H1i3Z1yzp.png)圖4

明顯的可以看出vectorize後的code可以接近快3x倍
那如果再加上AVX2=1的效果，又可以比vectorize的速度再快2x倍
![](https://hackmd.io/_uploads/Hy-vGJ1Ma.png)圖5

同理，測試test2及test3
在test2:
時間約為11.00s，如圖6
![](https://hackmd.io/_uploads/B1m3Eglza.png)圖6

在test3:
時間約為21.96s，如圖7
![](https://hackmd.io/_uploads/H1c8z-gzp.png)圖7


另外，Default vector registers on the PP machines，可以從下圖中發現，指令間的差距是16bytes，所以可以推斷其寬度是16bytes=128bits
![](https://hackmd.io/_uploads/rkILvk1MT.png)圖8

AVX2 register則是從下圖中可發現，指令間則是32bytes，可以推斷其寬度為32bytes=256bits
![](https://hackmd.io/_uploads/HJQkuykMT.png)圖9




## Q2-3
<font color="#f00">Q: Provide a theory for why the compiler is generating dramatically different assembly.</font>
A: 
![](https://hackmd.io/_uploads/Sy1RIExGT.png)圖10 

![](https://hackmd.io/_uploads/B14PK4xzT.png)圖11

```
for (int j = 0; j < N; j++)
    {
      /* max() */
      c[j] = a[j];
      if (b[j] > a[j])
        c[j] = b[j];
    }

```
圖10、11為上段程式碼所編譯出來的部分組語

![](https://hackmd.io/_uploads/r1tFvVxzp.png)圖12

![](https://hackmd.io/_uploads/ry0NYNef6.png)圖13

```
     for (int j = 0; j < N; j++)
     {
       /* max() */
-      c[j] = a[j];
-      if (b[j] > a[j])
-        c[j] = b[j];
+      if (b[j] > a[j]) c[j] = b[j];
+      else c[j] = a[j];
     }
   }
```

圖12、13為上圖修改後編譯出來的部分組語

前者有jmp指令而後者則是有movaps指令。
從C++ code的角度切入可以發現前者是先給值，再用if條件句(沒else)，這可能會讓compiler覺得有時需要跳，有時不用，可能就不適用向量指令(movaps)。然而後者的程式碼有if-else，反倒就可以藉由向量化的指令來給值。

雖然這邊的語義相同，但程式寫的順序就會造成組語的不同。