2016年6月24日 星期五

OpenMP : 極速開發平行化程式

 

OpenMP是我用過最方便的平行化方法! 不像GPU要對底層瞭若指掌,OpenMP沒加幾行就加速好幾倍^^




一、OpenMP and Fork-join Model


OpenMP 是一套支援跨平台共享記憶體方式的多執行緒並行的編程API,使用C,C++和Fortran語言,包括一套編譯器指令、庫和一些能夠影響執行行為的環境變數。

OpenMP提供的這種對於並列描述的高層抽象降低了並列編程的難度和複雜度,這樣程式設計師可以把更多的精力投入到並列演算法本身,而非其具體實作細節。

[感覺] 跟傳統的thread管理很像,只是變成更高階的寫法,開發速度更快!


程式設計師通過在原始碼中加入專用的 pragma 來指明自己的意圖,由此編譯器可以自動將程式進行並列化,並在必要之處加入同步互斥以及通訊。當選擇忽略這些 pragma,或者編譯器不支援OpenMP時,程式又可退化為通常的程式。

經由以下步驟載入openMP並指名平行化的程式區塊。

  1. 載入標頭檔 omp.h : #include <omp.h>
  2. 標記平行化的程式區塊
  3. 編譯使用編譯選項 -fopenmp




二、OpenMP 語法結構


OpenMP 語法結構如下:
#pragma omp <directive> [clause[[,] clause] ...]

1. Directive

  • 用於 parallel
    • for : 會將迴圈平行化處理 (ordered, 迴圈將依序的平行化執行)
    • parallel : 多個 thread 各執行一遍。
    • sections : section 平行化處理
    • barrier : thread 同步
  • 用於 single thread : master、single、critical
  • 用於 variable : atomic、flush、threadprivate

2. Clause : 用來控制變數在平行化時的處理方法

3. Function : 下面列出常用的

  • int omp_get_thread_num(void)
  • void omp_set_num_threads(int num_threads)
  • int omp_get_num_threads(void)

更多內容在 wiki 有詳細解說:

wiki - OpenMP
https://zh.wikipedia.org/zh-tw/OpenMP




三、例子


對 approximation method 的 American style Asian pricing Algorithm 的平行化,可以從重複同樣方法計算內插的地方著手。


要注意的是變數的存取,會有 race condition 的問題。下面是pragma擺放方式的範例,這裡用的是 parallel for。


最後跑一下benchmark,R code和C++ code速度相差大約27倍,有OpenMP的版本和普通的C++相差大約 3 倍 (很合理因為我是用四核cpu測的)。






References


wiki - OpenMP
https://zh.wikipedia.org/wiki/OpenMP

Parallelism, R, and OpenMP
https://wrathematics.github.io/RparallelGuide/

Parallelization in rcpp via OpenMP
https://wbnicholson.wordpress.com/2014/07/10/parallelization-in-rcpp-via-openmp/

aaz 的記憶倉庫 - OpenMP 心得 (一)
http://aaz-blogger.blogspot.tw/2011/03/openmp.html

簡易的程式平行化方法-OpenMP(一)簡介
https://kheresy.wordpress.com/2006/06/09/%E7%B0%A1%E6%98%93%E7%9A%84%E7%A8%8B%E5%BC%8F%E5%B9%B3%E8%A1%8C%E5%8C%96%E6%96%B9%E6%B3%95%EF%BC%8Dopenmp%EF%BC%88%E4%B8%80%EF%BC%89%E7%B0%A1%E4%BB%8B/








技術提供:Blogger.