最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

OpenMP 共享內(nèi)存的并行編程框架入門詳解

 更新時(shí)間:2022年11月11日 14:53:00   作者:一無是處的研究僧  
這篇文章主要為大家介紹了OpenMP 共享內(nèi)存的并行編程框架入門詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

簡介

OpenMP 一個(gè)非常易用的共享內(nèi)存的并行編程框架,它提供了一些非常簡單易用的API,讓編程人員從復(fù)雜的并發(fā)編程當(dāng)中釋放出來,專注于具體功能的實(shí)現(xiàn)。openmp 主要是通過編譯指導(dǎo)語句以及他的動(dòng)態(tài)運(yùn)行時(shí)庫實(shí)現(xiàn),在本篇文章當(dāng)中我們主要介紹 openmp 一些入門的簡單指令的使用。

認(rèn)識 openmp 的簡單易用性

比如現(xiàn)在我們有一個(gè)任務(wù),啟動(dòng)四個(gè)線程打印 hello world,我們看看下面 C 使用 pthread 的實(shí)現(xiàn)以及 C++ 使用標(biāo)準(zhǔn)庫的實(shí)現(xiàn),并對比他們和 openmp 的實(shí)現(xiàn)復(fù)雜性。

C 語言實(shí)現(xiàn)

#include <stdio.h>
#include <pthread.h>
void* func(void* args) {
  printf("hello world from tid = %ld\n", pthread_self());
  return NULL;
}
int main() {
  pthread_t threads[4];
  for(int i = 0; i < 4; i++) {
    pthread_create(&threads[i], NULL, func, NULL);
  }
  for(int i = 0; i < 4; i++) {
    pthread_join(threads[i], NULL);
  }
  return 0;
}

上面文件編譯命令:gcc 文件名 -lpthread 。

C++ 實(shí)現(xiàn)

#include <thread>
#include <iostream>
void* func() {
  printf("hello world from %ld\n", std::this_thread::get_id());
  return 0;
}
int main() {
  std::thread threads[4];
  for(auto &t : threads) {
    t = std::thread(func);
  }
  for(auto &t : threads) {
    t.join();
  }
  return EXIT_SUCCESS;
}

上面文件編譯命令:g++ 文件名 lpthread 。

OpenMP 實(shí)現(xiàn)

#include <stdio.h>
#include <omp.h>
int main() {
  // #pragma 表示這是編譯指導(dǎo)語句 表示編譯器需要對下面的并行域進(jìn)行特殊處理 omp parallel 表示下面的代碼區(qū)域 {} 是一個(gè)并行域 num_threads(4) 表示一共有 4 個(gè)線程執(zhí)行 {} 內(nèi)的代碼 因此實(shí)現(xiàn)的效果和上面的效果是一致的
  #pragma omp parallel num_threads(4)
  {
    printf("hello world from tid = %d\n", omp_get_thread_num()); // omp_get_thread_num 表示得到線程的線程 id
  }
  return 0;
}

上面文件編譯命令:gcc 文件名 -fopenmp ,如果你使用了 openmp 的編譯指導(dǎo)語句的話需要在編譯選項(xiàng)上加上 -fopenmp。

從上面的代碼來看,確實(shí) openmp 寫并發(fā)程序的復(fù)雜度確實(shí)比 pthreadC++ 低。openmp 相比起其他構(gòu)建并行程序的方式來說,使用 openmp 你可以更加關(guān)注具體的業(yè)務(wù)實(shí)現(xiàn),而不用太關(guān)心并發(fā)程序背后的啟動(dòng)與結(jié)束的過程,OenpMP 會(huì)幫我們實(shí)現(xiàn)很多細(xì)節(jié),讓程序的執(zhí)行符合我們的直覺。

opnemp 基本原理

在上文當(dāng)中我們寫了一個(gè)非常簡單的 openmp 程序,使用 4 個(gè)不同的線程分別打印 hello world 。我們仔細(xì)分析一下這個(gè)程序的執(zhí)行流程:

在 openmp 的程序當(dāng)中,你可以將程序用一個(gè)個(gè)的并行域分開,在并行域(parallel region)中,程序是有并發(fā)的,但是在并行域之外是沒有并發(fā)的,只有主線程(master)在執(zhí)行,整個(gè)過程如下圖所示:

現(xiàn)在我們用一個(gè)程序去驗(yàn)證上面的過程:

#include <stdio.h>
#include <omp.h>
#include <unistd.h>
int main() {
  #pragma omp parallel num_threads(4)
  {
    printf("parallel region 1 thread id = %d\n", omp_get_thread_num());
    sleep(1);
  }
  printf("after parallel region 1 thread id = %d\n", omp_get_thread_num());
  #pragma omp parallel num_threads(4)
  {
    printf("parallel region 2 thread id = %d\n", omp_get_thread_num());
    sleep(1);
  }
  printf("after parallel region 2 thread id = %d\n", omp_get_thread_num());
  #pragma omp parallel num_threads(4)
  {
    printf("parallel region 3 thread id = %d\n", omp_get_thread_num());
    sleep(1);
  }
  printf("after parallel region 3 thread id = %d\n", omp_get_thread_num());
  return 0;
}

程序執(zhí)行之后的一種輸出(還有很多其他的輸出形式,因?yàn)槭嵌嗑€程程序,線程的輸出是不確定的)如下所示:

parallel region 1 thread id = 0
parallel region 1 thread id = 3
parallel region 1 thread id = 1
parallel region 1 thread id = 2
after parallel region 1 thread id = 0
parallel region 2 thread id = 0
parallel region 2 thread id = 2
parallel region 2 thread id = 3
parallel region 2 thread id = 1
after parallel region 2 thread id = 0
parallel region 3 thread id = 0
parallel region 3 thread id = 1
parallel region 3 thread id = 3
parallel region 3 thread id = 2
after parallel region 3 thread id = 0

從上面的輸出我們可以了解到,id = 0 的線程就是主線程,在并行域內(nèi)部程序的輸出是沒有順序的,但是在并行域的外部是有序的,在并行域的開始部分程序會(huì)進(jìn)行并發(fā)操作,但是在并行域的最后會(huì)有一個(gè)隱藏的同步點(diǎn),等待所有線程到達(dá)這個(gè)同步點(diǎn)之后程序才會(huì)繼續(xù)執(zhí)行,現(xiàn)在再看上文當(dāng)中 openmp 的執(zhí)行流圖的話就很清晰易懂了。

積分例子

現(xiàn)在我們使用一個(gè)簡單的函數(shù)積分的例子去具體了解 openmp 在具體的使用場景下的并行。比如我們求函數(shù) x2x^2x2 的積分。

微元法的本質(zhì)就是將曲線下方的面積分割成一個(gè)一個(gè)的非常小的長方形,然后將所有的長方形的面積累加起來,這樣得到最終的結(jié)果。

如果你不懂上面所談到的求解方法也沒關(guān)系,只需要知道我們需要使用 openmp 去計(jì)算一個(gè)計(jì)算量比較大的任務(wù)即可。根據(jù)上面微元法的公式我們有一個(gè)非常大的求和公式,如果是在單線程的情況下我們使用一個(gè)循環(huán)就可以了,但是現(xiàn)在我們有多個(gè)線程,那么我們可以讓每個(gè)線程求某一個(gè)區(qū)間的和,最后將各個(gè)區(qū)間的和加起來得到最終的結(jié)果,這就是在并發(fā)場景下的實(shí)現(xiàn)思路。

openmp 具體的實(shí)現(xiàn)代碼如下所示:

#include <stdio.h>
#include <omp.h>
#include <math.h>
/// @brief 計(jì)算 x^2 一部分的面積
/// @param start 線程開始計(jì)算的位置
/// @param end   線程結(jié)束計(jì)算的位置
/// @param delta 長方形的邊長
/// @return 計(jì)算出來的面積
double x_square_partial_integral(double start, double end, double delta) {
  double s = 0;
  for(double i = start; i < end; i += delta) {
    s += pow(i, 2) * delta;
  }
  return s;
}
int main() {
  int s = 0;
  int e = 10;
  double sum = 0;
  #pragma omp parallel num_threads(32) reduction(+:sum)
  {
    // 根據(jù)線程號進(jìn)行計(jì)算區(qū)間的分配
    // omp_get_thread_num() 返回的線程 id 從 0 開始計(jì)數(shù) :0, 1, 2, 3, 4, ..., 31
    double start = (double)(e - s) / 32 * omp_get_thread_num();
    double end   = (double)(e - s) / 32 * (omp_get_thread_num() + 1);
    sum = x_square_partial_integral(start, end, 0.0000001);
  }
  printf("sum = %lf\n", sum);
  return 0;
}

在上面的代碼當(dāng)中 #pragma omp parallel num_threads(4) 表示啟動(dòng) 4 個(gè)線程執(zhí)行 {} 中的代碼,reduction(+:sum) 表示需要對 sum 這個(gè)變量進(jìn)行一個(gè)規(guī)約操作,當(dāng) openmp 中的線程遇到 reduction 子句的時(shí)候首先會(huì)拷貝一份 sum 作為本地變量,然后在并行域當(dāng)中使用的就是每一個(gè)線程的本地變量,因?yàn)橛?reduction 的規(guī)約操作,因此在每個(gè)線程計(jì)算完成之后還需要將每個(gè)線程本地計(jì)算出來的值對操作符 + 進(jìn)行規(guī)約操作,也就是將每個(gè)線程計(jì)算得到的結(jié)果求和,最終將得到的結(jié)果賦值給我們在 main 函數(shù)當(dāng)中定義的變量 sum 。最終我們打印的變量 sum 就是各個(gè)線程求和之后的結(jié)果。上面的代碼執(zhí)行過程大致如下圖所示:

注意事項(xiàng):你在編譯上述程序的時(shí)候需要加上編譯選項(xiàng) -fopenmp 啟動(dòng)openmp 編譯選項(xiàng)和 -lm 鏈接數(shù)學(xué)庫。

上面程序的執(zhí)行結(jié)果如下所示:

總結(jié)

在本篇文章當(dāng)中主要給大家介紹了 OpenMP 的基本使用和程序執(zhí)行的基本原理,在后續(xù)的文章當(dāng)中我們將仔細(xì)介紹各種 OpenMP 的子句和指令的使用方法

以上就是OpenMP 共享內(nèi)存的并行編程框架入門詳解的詳細(xì)內(nèi)容,更多關(guān)于OpenMP 共享內(nèi)存并行編程框架的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于C語言實(shí)現(xiàn)簡單的走迷宮游戲

    基于C語言實(shí)現(xiàn)簡單的走迷宮游戲

    這篇文章主要介紹了基于C語言實(shí)現(xiàn)簡單的走迷宮游戲,用到雙向隊(duì)列,方便在運(yùn)行完畢后輸出經(jīng)過的點(diǎn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-04-04
  • C語言中的while循環(huán)語句示例詳解

    C語言中的while循環(huán)語句示例詳解

    這篇文章主要介紹了C語言中的while循環(huán)語句,主要包括while循環(huán)的基本信息及常見問題,本文結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • C++日期類計(jì)算器的模擬實(shí)現(xiàn)舉例詳解

    C++日期類計(jì)算器的模擬實(shí)現(xiàn)舉例詳解

    兩個(gè)日期之間相隔天數(shù)的計(jì)算網(wǎng)上有許多的軟件,這里主要介紹如何使用C/C++語言來完成這樣的功能,下面這篇文章主要給大家介紹了關(guān)于C++日期類計(jì)算器的模擬實(shí)現(xiàn),需要的朋友可以參考下
    2023-04-04
  • C/C++內(nèi)存泄漏原因分析與應(yīng)對方法

    C/C++內(nèi)存泄漏原因分析與應(yīng)對方法

    內(nèi)存泄漏會(huì)導(dǎo)致當(dāng)前應(yīng)用程序消耗更多的內(nèi)存,使得其他應(yīng)用程序可用的內(nèi)存更少了,那么為什么會(huì)內(nèi)存泄漏,我們應(yīng)該怎樣應(yīng)對內(nèi)存泄漏,所以接下來就給大家詳細(xì)介紹一下C++內(nèi)存泄漏原因分析與應(yīng)對方法,需要的朋友可以參考下
    2023-07-07
  • C語言 實(shí)現(xiàn)輸入任意多個(gè)整數(shù)

    C語言 實(shí)現(xiàn)輸入任意多個(gè)整數(shù)

    這篇文章主要介紹了C語言 實(shí)現(xiàn)輸入任意多個(gè)整數(shù),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • C++11中的變長模板的示例詳解

    C++11中的變長模板的示例詳解

    C++中的變長模板真的是又臭又長,晦澀難懂,但是確實(shí)有些STL庫就是這么寫的。本文就來和大家聊聊C++11中這些變長模塊的使用,需要的可以參考一下
    2023-02-02
  • C語言實(shí)現(xiàn)簡易通訊錄完整流程

    C語言實(shí)現(xiàn)簡易通訊錄完整流程

    這篇文章主要為大家介紹了C語言實(shí)現(xiàn)簡易通訊錄的完整流程,每個(gè)環(huán)節(jié)都有完整代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-02-02
  • C語言中二維數(shù)組作為函數(shù)參數(shù)來傳遞的三種方法

    C語言中二維數(shù)組作為函數(shù)參數(shù)來傳遞的三種方法

    這篇文章主要給大家介紹了關(guān)于C語言中二維數(shù)組作為函數(shù)參數(shù)來傳遞的三種方法,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用C語言有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • C++語言 STL容器list總結(jié)

    C++語言 STL容器list總結(jié)

    這篇文章主要介紹了C++語言 STL容器list總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • C語言左旋字符串的三種實(shí)現(xiàn)方式

    C語言左旋字符串的三種實(shí)現(xiàn)方式

    本文章將使用三種思路實(shí)現(xiàn)字符串的左旋(循環(huán)移動(dòng),截取和拼接,逆序反轉(zhuǎn)),文中通過代碼示例和圖文介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下
    2024-03-03

最新評論

梅州市| 布拖县| 广昌县| 曲沃县| 青州市| 九台市| 马鞍山市| 大方县| 许昌市| 龙海市| 沙坪坝区| 南昌县| 西城区| 阿克| 焦作市| 宜良县| 大余县| 安岳县| 乐山市| 郓城县| 广汉市| 佛坪县| 平利县| 鄂托克旗| 筠连县| 称多县| 瓮安县| 临海市| 舟山市| 巨鹿县| 贡嘎县| 鹤壁市| 临高县| 莱西市| 峨边| 襄城县| 怀柔区| 周至县| 襄汾县| 临沂市| 海兴县|