程序運行速度慢應該是所有程序員都特別頭疼的一個問題,當前對於程序運行加速有兩種方式:一種是通過硬件的方式加速,比如我們常聽說的硬解碼,軟解碼,這裏的硬解碼就是通過硬件對程序進行加速;一種是通過軟件的方式進行加速,而這種方式使用比較多的是使用共享存儲編程。當前對於共享存儲編程有三種標準:Pthreads,X3H5,OpenMP(最流行)。
OpenMP是一個支持共享存儲並行設計的庫,特別適宜多核CPU上的並行程序設計,由一系列編譯指導語句和庫函數組成,說白了就是一個開源庫,和OpenCV差不多,只不過一個做並行處理庫,一個是計算機視覺庫。
一、fork/join並行執行模式
OpenMP使用的fork/join並行執行模式。
OpenMP並行執行的程序要執行完並行執行區域後才能執行主線程。這就是標準的並行模式fork/join式並行模式。因此,標準並行模式執行代碼的基本思想是,程序開始時只有一個主線程,程序中的串行部分都由主線程執行,並行的部分是通過派生其他線程來執行,關閉並行區域前,主線程等待其他線程到達,也就是說,如果並行部分沒有結束時是不會執行串行部分的。(實際上,這個“等待”就是一次“隱式同步”)。
二、如何應用OpenMP?
1. OpenMP常用於循環並行化; 找出最耗時的循環,在串行程序上加上編譯指導語句實現並行處理,當然咯,只要每次循環互不相干,互不影響才能做成並行。
2. OpenMP常用於互不相關的兩端或多端代碼塊的並行執行;比如在疲勞檢測中要視線眨眼檢測和哈欠檢測,那麼這個眨眼檢測和哈欠檢測就可以做成並行處理。
三、OpenMP程序結構
據我所知,當前OpenMP支持C、C++和fortran語言,下面就簡單的寫一個基於C/C++語言的OpenMP程序的結構。
#include<omp.h>
int main(int argc, char *argv)
{
#pragma omp parallel
{
printf("i like c++ programming!\n");
}
system("pause");
return 0;
}
程序運行結果如下:可以看得出parallel語句中的代碼被執行了八次,說明總共創建了8個線程去執行parallel語句中的代碼,這個創建多少個線程與CPU的核數有關,我的電腦是八核的,所以創建了8個線程,代碼被執行了八次。
四、並行執行特點
在瞭解OpenMP並行執行的特點前先看個OpenMP小程序。
#include <iostream>
#include<omp.h>
int main(int argc, char *argv)
{
printf("串行打印:\n");
for (int i = 0; i < 10; i++)
printf("%d, ", i);
printf("\n");
printf("並行打印:\n");
#pragma omp parallel for
for (int i = 0; i < 10; i++)
printf("%d, ", i);
printf("\n");
system("pause");
return 0;
}
程序運行結果可見for 循環語句中的內容被並行執行了。(每次運行的打印結果可能會有區別)。這裏要說明一下,#pragma omp parallel for 這條語句是用來指定後面的for循環語句變成並行執行的,這算是是OpenMP語句入門級的使用,也是使用最頻繁的一條語句。當然咯,for循環裏的內容必須滿足可以並行執行,即每次循環互不相干,後一次循環不依賴於前面的循環。
五、並行執行效率
將for循環裏的語句變成並行執行後效率會不會提高呢,我想這是我們最關心的內容了。下面就寫一個簡單的測試程序來測試一下:
#include<time.h>
#include<iostream>
#include<omp.h>
void test()
{
int a = 0;
clock_t t1 = clock();
for (int i = 0; i < 100000000; i++)
{
a = i + 1;
}
clock_t t2 = clock();
printf("Time = %d\n", t2 - t1);
}
int main(int argc, char* argv[])
{
clock_t t1 = clock();
#pragma omp parallel for
for (int j = 0; j < 2; j++){
test();
}
clock_t t2 = clock();
printf("Total time = %d\n", t2 - t1);
test();
return 0;
}
在test()函數中,執行了1億次循環,主要是用來執行一個長時間的操作。在main()函數裏,先在一個循環裏調用test()函數,只循環2次,我們還是看一下在雙核CPU上的運行結果吧:
Time = 297
Time = 297
Total time = 297
Time = 297
可以看到在for循環裏的兩次test()函數調用都花費了297ms, 但是打印出的總時間卻只花費了297ms,後面那個單獨執行的test()函數花費的時間也是297ms,可見使用並行計算後效率提高了整整一倍。上面有講了使用最頻繁的編譯指導語句#pragma omp parallelfor,下面的博客會接着講一些最常用的一些編譯指導語句。
最後說一下,如何在Visual Studio這個IDE中開啓OpenMP並行,打開過程如下:
項目屬性->配置屬性->C\C++ ->語言->OpenMP支持->是 (/openmp)
參考文獻:
http://wenku.baidu.com/link?url=A-NdON4QI-9iKsRNrlw2mrqGoH2hynDhnZRXPpAWFJRnaNpoAx48tnVj3VYqieGzwJAWRlvR6cupiwCQ6rm0NlICCaPBT7cVVIkmHeHl8wa