1. 程式人生 > >OpenMP多執行緒

OpenMP多執行緒

OpenMP並行程式設計           轉載:http://blog.csdn.net/augusdi/article/details/8807119           OpenMP是一個支援共享儲存並行設計的庫,特別適宜多核CPU上的並行程式設計。今天在雙核CPU機器上試了一下OpenMP並行程式設計,發現效率方面超出想象,因此寫出來分享給大家。           在VC8.0中專案的屬性對話方塊中,左邊框裡的“配置屬性”下的“C/C++”下的“語言”頁裡,將OpenMP支援改為“是/(OpenMP)”就可以支援OpenMP了。           先看一個簡單的使用了OpenMP程式
  1. int
     main(int argc, char* argv[])  
  2. {  
  3. #pragma omp parallel for
  4.     for (int i = 0; i < 10; i++ )  
  5.     {  
  6.         printf("i = %d/n", i);  
  7.     }  
  8.     return 0;  
  9. }  

這個程式執行後打印出以下結果: i = 0 i = 5 i = 1 i = 6 i = 2 i = 7 i = 3 i = 8 i = 4 i = 9           可見for 迴圈語句中的內容被並行執行了。(每次執行的列印結果可能會有區別)           這裡要說明一下,#pragma
 omp parallel for 這條語句是用來指定後面的for迴圈語句變成並行執行的,當然for迴圈裡的內容必須滿足可以並行執行,即每次迴圈互不相干,後一次迴圈不依賴於前面的迴圈。           有關#pragma omp parallel for 這條語句的具體含義及相關OpenMP指令和函式的介紹暫時先放一放,只要知道這條語句會將後面的for迴圈裡的內容變成並行執行就行了。           將for迴圈裡的語句變成並行執行後效率會不會提高呢,我想這是我們最關心的內容了。下面就寫一個簡單的測試程式來測試一下:
  1. void test()  
  2. {  
  3.     int a = 0;  
  4.     clock_t t1 = clock();  
  5.     for (int i = 0; i < 100000000; i++)  
  6.     {  
  7.         a = i+1;  
  8.     }  
  9.     clock_t t2 = clock();  
  10.     printf("Time = %d/n", t2-t1);  
  11. }  
  12. int main(int argc, char* argv[])  
  13. {  
  14.     clock_t t1 = clock();  
  15. #pragma omp parallel for
  16.     for ( int j = 0; j < 2; j++ ){  
  17.         test();  
  18.     }  
  19.     clock_t t2 = clock();  
  20.     printf("Total time = %d/n", t2-t1);  
  21.     test();  
  22.     return 0;  
  23. }  
          在test()函式中,執行了1億次迴圈,主要是用來執行一個長時間的操作。           在main()函式裡,先在一個迴圈裡呼叫test()函式,只迴圈2次,我們還是看一下在雙核CPU上的執行結果吧: Time = 297 Time = 297 Total time = 297 Time = 297           可以看到在for迴圈裡的兩次test()函式呼叫都花費了297ms, 但是打印出的總時間卻只花費了297ms,後面那個單獨執行的test()函式花費的時間也是297ms,可見使用平行計算後效率提高了整整一倍。           下一篇文章中將介紹OpenMP的具體指令和用法。 OpenMP並行程式設計

fork/join並行執行模式的概念

          OpenMP是一個編譯器指令和庫函式的集合,主要是為共享式儲存計算機上的並行程式設計使用的。           前面一篇文章中已經試用了OpenMP的一個Parallel for指令。從上篇文章中我們也可以發現OpenMP並行執行的程式要全部結束後才能執行後面的非並行部分的程式碼。這就是標準的並行模式fork/join式並行模式,共享儲存式並行程式就是使用fork/join式並行的。 標準並行模式執行程式碼的基本思想是,程式開始時只有一個主執行緒,程式中的序列部分都由主執行緒執行,並行的部分是通過派生其他執行緒來執行,但是如果並行部分沒有結束時是不會執行序列部分的,如上一篇文章中的以下程式碼:
  1. int main(int argc, char* argv[])  
  2. {  
  3. clock_t t1 = clock();  
  4. #pragma omp parallel for
  5. for ( int j = 0; j < 2; j++ ){  
  6. test();  
  7. }  
  8. clock_t t2 = clock();  
  9. printf("Total time = %d/n", t2-t1);  
  10. test();  
  11. return 0;  
  12. }  
          在沒有執行完for迴圈中的程式碼之前,後面的clock_t t2 = clock();這行程式碼是不會執行的,如果和呼叫執行緒建立函式相比,它相當於先建立執行緒,並等待執行緒執行完,所以這種並行模式中在主執行緒裡建立的執行緒並沒有和主執行緒並行執行。

OpenMP指令和庫函式介紹

          下面來介紹OpenMP的基本指令和常用指令的用法,           在C/C++中,OpenMP指令使用的格式為 pragma omp 指令 [子句[子句]…]           前面提到的parallel for就是一條指令,有些書中也將OpenMP的“指令”叫做“編譯指導語句”,後面的子句是可選的。例如: #pragma omp parallel private(i,  j) parallel 就是指令, private是子句           為敘述方便把包含#pragma和OpenMP指令的一行叫做語句,如上面那行叫parallel語句。           OpenMP的指令有以下一些: parallel,用在一個程式碼段之前,表示這段程式碼將被多個執行緒並行執行。 for,用於for迴圈之前,將迴圈分配到多個執行緒中並行執行,必須保證每次迴圈之間無相關性。 parallel for, parallel 和 for語句的結合,也是用在一個for迴圈之前,表示for迴圈的程式碼將被多個執行緒並行執行。 sections,用在可能會被並行執行的程式碼段之前。 parallel sections,parallel和sections兩個語句的結合。 critical,用在一段程式碼臨界區之前。 single,用在一段只被單個執行緒執行的程式碼段之前,表示後面的程式碼段將被單執行緒執行。 flush,更新並行區域裡的共享變數進行的修改,確保並行的多執行緒對共享變數的讀操作是最新值。 barrier,用於並行區內程式碼的執行緒同步,所有執行緒執行到barrier時要停止,直到所有執行緒都執行到barrier時才繼續往下執行。 atomic,用於指定一塊記憶體區域被自動更新。 master,用於指定一段程式碼塊由主執行緒執行。 ordered, 用於指定並行區域的迴圈按順序執行。 threadprivate, 用於指定一個變數是執行緒私有的。           OpenMP除上述指令外,還有一些庫函式,下面列出幾個常用的庫函式: omp_get_num_procs, 返回執行本執行緒的多處理機的處理器個數。 omp_get_num_threads, 返回當前並行區域中的活動執行緒個數。 omp_get_thread_num, 返回執行緒號。 omp_set_num_threads, 設定並行執行程式碼時的執行緒個數。 omp_init_lock, 初始化一個簡單鎖。 omp_set_lock, 上鎖操作。 omp_unset_lock, 解鎖操作,要和omp_set_lock函式配對使用。 omp_destroy_lock, omp_init_lock函式的配對操作函式,關閉一個鎖。 OpenMP的子句有以下一些 private, 指定每個執行緒都有它自己的變數私有副本。 firstprivate指定每個執行緒都有它自己的變數私有副本,並且變數要被繼承主執行緒中的初值。 lastprivate主要是用來指定將執行緒中的私有變數的值在並行處理結束後複製回主執行緒中的對應變數。 reduce用來指定一個或多個變數是私有的,並且在並行處理結束後這些變數要執行指定的運算。 nowait忽略指定中暗含的等待。 num_threads,指定執行緒的個數。 schedule,指定如何排程for迴圈迭代。 shared指定一個或多個變數為多個執行緒間的共享變數。 ordered用來指定for迴圈的執行要按順序執行。 copyprivate用於single指令中的指定變數為多個執行緒的共享變數。 copyin用來指定一個threadprivate的變數的值要用主執行緒的值進行初始化。 default用來指定並行處理區域內的變數的使用方式,預設是shared。

parallel 指令的用法

          parallel 是用來構造一個並行塊的,也可以使用其他指令如for、sections等和它配合使用。           在C/C++中,parallel的使用方法如下:
  1. #pragma omp parallel [for | sections] [子句[子句]…]
  2. {  
  3. //程式碼
  4. }  
parallel語句後面要跟一個大括號對將要並行執行的程式碼括起來。
  1. void main(int argc, char *argv[]) {  
  2. #pragma omp parallel 
  3. {  
  4.       printf(“Hello, World!/n”);  
  5. }  
  6. }  
執行以上程式碼將會打印出以下結果 Hello, World! Hello, World! Hello, World! Hello, World! 可以看得出parallel語句中的程式碼被執行了四次,說明總共建立了4個執行緒去執行parallel語句中的程式碼。 也可以指定使用多少個執行緒來執行,需要使用num_threads子句:
  1. void main(int argc, char *argv[]) {  
  2. #pragma omp parallel num_threads(8)
  3. {  
  4.     printf(“Hello, World!, ThreadId=%d/n”, omp_get_thread_num() );  
  5. }  
  6. }  
執行以上程式碼,將會打印出以下結果: Hello, World!, ThreadId = 2 Hello, World!, ThreadId = 6 Hello, World!, ThreadId = 4 Hello, World!, ThreadId = 0 Hello, World!, ThreadId = 5 Hello, World!, ThreadId = 7 Hello, World!, ThreadId = 1 Hello, World!, ThreadId = 3     從ThreadId的不同可以看出建立了8個執行緒來執行以上程式碼。所以parallel指令是用來為一段程式碼建立多個執行緒來執行它的。parallel塊中的每行程式碼都被多個執行緒重複執行。 和傳統的建立執行緒函式比起來,相當於為一個執行緒入口函式重複呼叫建立執行緒函式來建立執行緒並等待執行緒執行完。

for指令的使用方法

         for指令則是用來將一個for迴圈分配到多個執行緒中執行。for指令一般可以和parallel指令合起來形成parallel for指令使用,也可以單獨用在parallel語句的並行塊中。 #pragma omp [parallel] for [子句] for迴圈語句 先看看單獨使用for語句時是什麼效果:
  1. int j = 0;  
  2. #pragma omp for
  3. for ( j = 0; j < 4; j++ ){  
  4. 相關推薦

    OpenMP: 執行檔案操作

    OpenMP:多執行緒檔案操作 簡介 具體實現 1. OpenMP常用函式 2. 並行區域 3. for 迴圈並行化基本用法 3.1 資料不相關性 3.2 for迴圈並行化的幾

    Caffe:CPU模式下使用openblas-openmp(執行版本)

    從所周知,所有的深度學習框架使用GPU執行是最快的,但是在不具備Nvidia顯示卡的環境下只使用CPU來執行,慢就慢點吧,對於學習階段還是夠用的。 Caffe用到的Blas可以選擇Altas,OpenBlas,Intel MKL,Blas承擔了大量了數學工作,

    OpenMP執行

    OpenMP並行程式設計           轉載:http://blog.csdn.net/augusdi/article/details/8807119           OpenMP是一個支援共享儲存並行設計的庫,特別適宜多核CPU上的並行程式設計。今

    OpenMP執行計算過程中任務排程問題

    對於OpenMP的任務排程主要針對於並行的for迴圈,當每一次迴圈過程中的計算時間複雜度不一致的時候,簡單的給每一個執行緒分配相同次數的迭代,會導致執行緒計算負載不均衡。不僅如此,對於實時計算的計算機,每一個核心的佔用率是不一樣的。針對該問題,OpenMP中給出

    使用OpenMP進行執行處理時,如何退出執行

           在進行多執行緒程式設計時,OpenMP是個非常有效的工具,它能最大化的將你的並行處理髮揮到極致。當然有如此便利的方面,自然也會有相應的限制條件。但是一旦熟悉使用,注意它的那幾個原則,也不會有什麼問題。        在最近的工作中,遇到了一種情況,內容如下:在

    CP2K4.1-release & 最新5.x-development 程序執行(MPI+OPENMP) (psmp版 & popt版)超詳細編譯安裝教程極致優化加速版(全編譯器可編譯版)

    CP2K 4.1-release & 最新5.x-development 多程序多執行緒(MPI+OPENMP) (psmp版 & popt版)超詳細編譯安裝教程極致優化加速版(全

    Windbg除錯----執行控制除錯

    在除錯程式的時候,可能經常會有這樣的需求,讓一個執行緒在特定的時候才讓其開始執行或者暫停執行。比如複雜的多執行緒導致死鎖的問題,又或者多執行緒中的Race Condition 導致程式執行異常等。 很多時候,我們可以藉助編寫除錯程式碼來達到多執行緒的除錯,可是有些情況下除錯的執行粒度是指

    Java執行實現電影院售票案例

    某電影院目前正在上映賀歲大片,共有100張票,而它有3個售票視窗,請設計一個程式模擬該電影院售票。 定義Sell類實現Runnable介面,很好的解決了單繼承共享資源問題 public class Sell implements Runnable { // 定義100張票,三個售票

    Objective-C高階程式設計:iOS與OS X執行和記憶體管理

    這篇文章主要給大家講解一下GCD的平時不太常用的API,以及文末會貼出GCD定時器的一個小例子。 需要學習的朋友可以通過網盤免費下載pdf版 (先點選普通下載-----再選擇普通使用者就能免費下載了)http://putpan.com/fs/cy1i1beebn7s0h4u9/ 1.G

    java執行物件鎖、類鎖、同步機制詳解

    1.在java多執行緒程式設計中物件鎖、類鎖、同步機制synchronized詳解:     物件鎖:在java中每個物件都有一個唯一的鎖,物件鎖用於物件例項方法或者一個物件例項上面的。     類鎖:是用於一個類靜態方法或者class物件的,一個

    面試題 執行 順序操作

    問題 編寫一個程式,程式會啟動4個執行緒,向4個檔案A,B,C,D裡寫入資料,每個執行緒只能寫一個值。 執行緒A:只寫1 執行緒B:只寫2 執行緒C:只寫3 執行緒D:只寫4 4個檔案A,B,C,D。 程式執行起來,4個檔案的寫入結果如下:

    Python執行程序和協程的例項講解

    執行緒、程序和協程是什麼 執行緒、程序和協程的詳細概念解釋和原理剖析不是本文的重點,本文重點講述在Python中怎樣實際使用這三種東西 參考: 程序、執行緒、協程之概念理解 程序(Process)是計算機中的程式關於某資料集合上的一次執行活動,是系統進行資源分配和排程的基本單位,是作業系統結構的基礎。執

    Java 執行實現死鎖場景

    簡述: 《Java 程式設計思想》  P718 ~ P722 模擬死鎖的場景, 三個人 三根筷子,每個人需要拿到身邊的兩根筷子才能開始吃飯 出現死鎖的場景是,三個人都拿到了右邊的筷子,但是由於筷子都被搶佔,均無法獲得左邊的筷子 Chopstick.java

    Java 執行 join和interrupt 方法

    簡述: 使用Java多執行緒中join和interrupt函式 《Java程式設計思想》 P669 ~ P670 一個執行緒可以再其他執行緒上呼叫join()方法,其效果是等待一段時間直到第二個執行緒結束才繼續執行。 如果某個執行緒在另一個執行緒t上呼叫t.join(), 此

    Java 執行 CountDownLatch 試用

    簡述: 使用Java多執行緒的庫,包括 ExecutorService執行緒池, CountDownLatch執行緒執行控制(知道所有啟動的執行緒呼叫完成後,函式才會繼續執行) package test.anialy.multithread; import java.ut

    執行筆試面試概念問答

    點選此處檢視原文 第一題:執行緒的基本概念、執行緒的基本狀態及狀態之間的關係? 執行緒,有時稱為輕量級程序,是程式執行流的最小單元。一個標準的執行緒由執行緒ID,當前指令指標(PC),暫存器集合和堆疊組成。另外,執行緒是程序中的一個實體,是被系統獨立排程和分派的基本單位。它與屬於同一程序的其

    Python爬蟲之執行程序

    前言 我們之前寫的爬蟲都是單個執行緒的?這怎麼夠?一旦一個地方卡到不動了,那不就永遠等待下去了?為此我們可以使用多執行緒或者多程序來處理。 首先宣告一點! 多執行緒和多程序是不一樣的!一個是 thread 庫,一個是 multiprocessing 庫。而多執行緒 thread 在 Pytho

    java面試/筆試題目之執行及鎖 (持續更新中)

    前言:這一模組可以參照徐劉根大佬的部落格。 一.執行緒和程序的概念、並行和併發的概念 1.程序:是計算機中的程式關於某資料集合上的一次執行活動,是系統 進行資源分配和排程的基本單位,是作業系統結構的基礎。程式是指令、資料及其組織形式的描述,程序是程式的實體。 2.執行緒:是程式執行流的

    執行之join方法

    一.前言:        在很多情況下,我們都是通過主執行緒建立並啟動子執行緒的,如果子執行緒中需要耗費大量的時間計算的話,主執行緒往往會比子執行緒先結束,這個時候就會導致有時候主執行緒想獲取子執行緒計算之後的結果,但是卻獲取不到。這個時候,我們就可以通過

    執行之可見性:volatile

    一.什麼是volatile,它的作用是什麼 我們知道執行緒安全的三大核心就是原子性、可見性和順序性,synchronized可以實現原子性,而volatile就是來實現可見性。 那麼什麼是可見性呢? 我們知道,在現代計算機中,由於 CPU 直接從主記憶體中讀取資料的效率不高,所以都會對應