目前很多移動端的深度學(xué)習(xí)前向運算框架都用到openmp,如ncnn、paddlelite、mace等。所以這篇來介紹一些OpenMP并行編程。
OpenMP是什么
官方的介紹是:OpenMP(Open Multi-Processing,開放多處理)是一種支持多平臺共享存儲器多處理器編程的C/C++和Fortran語言的規(guī)范和API。說的通俗一些就是:在單機上使用的多線程編程的規(guī)范和API。為什么是單機呢,因為比如計算機集群,是非共享內(nèi)存系統(tǒng),在非共享內(nèi)存系統(tǒng)上,MPI(Message Passing Interface)或MapReduce會更合適。
openmp.png
OpenMP API
OpenMP API包括以下三部分:1)編譯器偽指令;2)運行時函數(shù);3)環(huán)境變量。
- 編譯器偽指令
在OpenMP支持的C/C++語言中,OpenMP的使用如下:
#pragma omp 指令[子句[,子句] …] //編譯制導(dǎo)指令
{ //左大括號和右大括號必須各占一行
code;
}
下面舉個例子:
#include <iostream>
#include "omp.h" //OpenMP頭文件
using namespace std;
void main()
{
#pragma omp parallel //OpenMP編寫開始
{
cout << "Test" << endl;
}
system("pause");
}
編譯制導(dǎo)指令以#pragma omp開頭,后面跟具體的功能指令。具體的功能指令使用時可查找:https://www.openmp.org/wp-content/uploads/openmp-examples-4.5.0.pdf
- 運行時函數(shù)
除了通過編譯器偽指令支持多線程編程,OpenMP還有一些支持顯式編程的函數(shù)。
-- omp_in_parallel:判斷當(dāng)前是否在并行域中
-- omp_get_thread_num:返回線程號
-- omp_set_num_threads:設(shè)置后續(xù)并行域中的線程格式
-- omp_get_num_threads:返回當(dāng)前并行區(qū)域中的線程數(shù)
-- omp_get_max_threads:獲取并行域可用的最大線程數(shù)目
-- omp_get_num_procs:返回系統(tǒng)中處理器的個數(shù)
-- omp_get_dynamic:判斷是否支持動態(tài)改變線程數(shù)目
--omp_set_dynamic:啟用或關(guān)閉線程數(shù)目的動態(tài)改變
-- omp_get_nested:判斷系統(tǒng)是否支持并行嵌套
-- omp_set_nested:啟用或關(guān)閉并行嵌套
-- omp_init_lock:初始化鎖
-- omp_set_lock:獲得鎖
-- omp_unset_lock:釋放鎖
-- omp_destroyed_lock:銷毀鎖 - 環(huán)境變量
OpenMP環(huán)境變量是指一些影響OpenMP運行時行為的配置。OpenMP環(huán)境變量的優(yōu)先級低于函數(shù)和偽指令。
-- OMP_SCHEDULE指定了運行時負載均衡類型和每次任務(wù)分配的循環(huán)次數(shù)。
-- OMP_NUM_THREADS指定了執(zhí)行并行區(qū)域時使用的默認線程數(shù)量。
-- OMP_DYNAMIC決定了是否允許調(diào)整執(zhí)行并行區(qū)域的線程數(shù)量,如果設(shè)置位ture,則OpenMP運行時可能會調(diào)整執(zhí)行并行區(qū)域的線程數(shù)量,以優(yōu)化系統(tǒng)資源的使用。
-- OMP_PROC_BIND決定了是否允許線程遷移到其他的處理器上執(zhí)行。如果位true,則運行時不會在處理器間遷移線程。
-- OMP_NESTED決定了是否支持嵌套線程,如果位true,則支持。
-- OMP_STACKSIZE指定了每個線程擁有的棧大小,如果出現(xiàn)棧溢出,應(yīng)該將其改大。
-- OMP_THREAD_LIMIT指定了系統(tǒng)能夠創(chuàng)建的OpenMP線程的最大值。