---
# System prepended metadata

title: 'Programming Assignment VI: OpenCL Programming'
tags: [NYCU Parallel Programming f23]

---

# Programming Assignment VI: OpenCL Programming

###### tags: `NYCU Parallel Programming f23`

[TOC]

## Explain your implementation. How do you optimize the performance of convolution?

### 1. Memory Coalescing

Memory Coalescing 是指在GPU記憶體存取中將多個請求合併為單一請求，以提高記憶體存取效率的一種優化技術。在本次作業中，我透過盡可能讓同 warp 中的 threads 去讀取連續的記憶體區段，來達到 Memory Coalescing 的效果。

在 OpenCL 中，work item 的維度順序會影響 threads 間的連續性。如下圖
![image](https://hackmd.io/_uploads/rJQeBxcDT.png)
剛開始寫的時候我是以 height 為第一個維度，故 threads 是在 height 方向上為連續，但我們的圖片是以 width 方向連續儲存，故將 height 設為第一個維度無法觸發 Memory Coalescing。後來我將維度修改成下圖後即可觸發 Memory Coalescing :
![image](https://hackmd.io/_uploads/rkCzLe9wT.png)


以下3圖顯示`未採用` Memory Coalescing 的 speedup :
* `./conv -f 1`
![image](https://hackmd.io/_uploads/HkoTme5DT.png)
* `./conv -f 2`
![image](https://hackmd.io/_uploads/rks-4e5wT.png)
* `./conv -f 3`
![image](https://hackmd.io/_uploads/SyQf4eqDa.png)

以下3圖顯示`採用` Memory Coalescing 的 speedup :
* `./conv -f 1`
![image](https://hackmd.io/_uploads/S1v_Ul5D6.png)
* `./conv -f 2`
![image](https://hackmd.io/_uploads/Hy-K8lqDp.png)
* `./conv -f 3`
![image](https://hackmd.io/_uploads/SyG9Lxcv6.png)

可以看出 speedup 有明顯提升。

### 2. Local Memory

Local memory 是一種在運算裝置上特別設計的記憶體空間，主要用於同一個 group 內的 work items 之間共享數據。這種記憶體位於每個 compute unit 上，並且相較於 global memory，它的存取速度要快得多。在本次作業中我透過將各 group 中，需要重複使用的 data 先存入 local memory，以減少 global memory 的讀取次數。

Group 中的每個 threads 平均分攤一部分的 global memory 資料讀取，下圖為 group 需要讀取的資料範圍示意圖。除了要讀取對應 group 範圍內的 pixels 進 local memory 以外，由於卷積運算的性質，故我們必須也將周圍一部分資料也一併讀取近來 (convolution range)。

同時，讀取資料的方式也會利用到 `Memory Coalescing` 進行加速。 

![image](https://hackmd.io/_uploads/HJkUcecPT.png)

以下3圖顯示加入 Local Memory 後的 speedup :
* `./conv -f 1`
![image](https://hackmd.io/_uploads/SJph2g9D6.png)
* `./conv -f 2`
![image](https://hackmd.io/_uploads/rJHphgqvp.png)
* `./conv -f 3`
![image](https://hackmd.io/_uploads/ryoThgqv6.png)


### 3. CL_MEM_USE_HOST_PTR

在 OpenCL 中，`CL_MEM_USE_HOST_PTR` 是一種用於建立緩衝區（buffer）的 flag。當使用這個旗標時，它指示 OpenCL 使用一塊已經由 host 分配的記憶體。在 clCreateBuffer 中使用 CL_MEM_USE_HOST_PTR 後可以減少數據在不同記憶體空間之間的移動，進一步提高性能。

以下3圖顯示使用 CL_MEM_USE_HOST_PTR 後的 speedup :
* `./conv -f 1`
![image](https://hackmd.io/_uploads/HkYjKlmda.png)
* `./conv -f 2`
![image](https://hackmd.io/_uploads/r1bx9lXd6.png)
* `./conv -f 3`
![image](https://hackmd.io/_uploads/Syrrqe7O6.png)


### 4. Constant Memory

對於需要頻繁讀取、所有 groups 共享、記憶體占用量不大且無須修改內容的 convolution filter，可以放在讀取效率較高的 constant memory 中，以提高性能。

以下3圖顯示將 convolution filter 放到 constant memory 後的 speedup :
* `./conv -f 1`
![image](https://hackmd.io/_uploads/HkDLslmO6.png)
* `./conv -f 2`
![image](https://hackmd.io/_uploads/Skp8ox7Op.png)
* `./conv -f 3`
![image](https://hackmd.io/_uploads/rkXvsgQdT.png)

最後實現了最高 `56.31x` 的加速 !


