溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

OPENMP?SECTIONS?CONSTRUCT原理是什么

發(fā)布時間:2023-03-06 15:12:58 來源:億速云 閱讀:85 作者:iii 欄目:開發(fā)技術(shù)

今天小編給大家分享一下OPENMP SECTIONS CONSTRUCT原理是什么的相關(guān)知識點,內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

編譯器角度分析

在這一小節(jié)當(dāng)中我們將從編譯器角度去分析編譯器會怎么處理 sections construct ,我們以下面的 sections construct 為例子,看看編譯器是如何處理 sections construct 的。

#pragma omp sections
{
  #pragma omp section
  stmt1;
  #pragma omp section
  stmt2;
  #pragma omp section
  stmt3;
}

上面的代碼會被編譯器轉(zhuǎn)換成下面的形式,其中 GOMP_sections_start 和 GOMP_sections_next 是并發(fā)安全的,他們都會返回一個數(shù)據(jù)表示第幾個 omp section 代碼塊,其中 GOMP_sections_start 的參數(shù)是表示有幾個 omp section 代碼塊,并且返回給線程一個整數(shù)表示線程需要執(zhí)行第幾個 section 代碼塊,這兩個函數(shù)的意義不同的是在 GOMP_sections_start 當(dāng)中會進(jìn)行一些數(shù)據(jù)的初始化操作。當(dāng)兩個函數(shù)返回 0 的時候表示所有的 section 都被執(zhí)行完了,從而退出 for 循環(huán)。

for (i = GOMP_sections_start (3); i != 0; i = GOMP_sections_next ())
  switch (i)
    {
    case 1:
      stmt1;
      break;
    case 2:
      stmt2;
      break;
    case 3:
      stmt3;
      break;
    }
GOMP_barrier ();

動態(tài)庫函數(shù)分析

事實上在函數(shù) GOMP_sections_start 和函數(shù) GOMP_sections_next 當(dāng)中調(diào)用的都是我們之前分析過的函數(shù) gomp_iter_dynamic_next ,這個函數(shù)實際上就是讓線程始終原子指令去競爭數(shù)據(jù)塊(chunk),這個特點和 sections 需要完成的語意是相同的,只不過 sections 的塊大小(chunk size)都是等于 1 的,因為一個線程一次只能夠執(zhí)行一個 section 代碼塊。

unsigned
GOMP_sections_start (unsigned count)
{
  // 參數(shù) count 的含義就是表示一共有多少個 section 代碼塊
  // 得到當(dāng)線程的相關(guān)數(shù)據(jù)
  struct gomp_thread *thr = gomp_thread ();
  long s, e, ret;
  // 進(jìn)行數(shù)據(jù)的初始化操作
  // 將數(shù)據(jù)的 chunk size 設(shè)置等于 1
  // 分割 chunk size 的起始位置設(shè)置成 1 因為根據(jù)上面的代碼分析 0 表示退出循環(huán) 因此不能夠使用 0 作為分割的起始位置
  if (gomp_work_share_start (false))
    {
    // 這里傳入 count 作為參數(shù)的原因是需要設(shè)置 chunk 分配的最終位置 具體的源代碼在下方
      gomp_sections_init (thr->ts.work_share, count);
      gomp_work_share_init_done ();
    }
  // 如果獲取到一個 section 的執(zhí)行權(quán) gomp_iter_dynamic_next 返回 true 否則返回 false 
  // s 和 e 分別表示 chunk 的起始位置和終止位置 但是在 sections 當(dāng)中需要注意的是所有的 chunk size 都等于 1
  // 這也很容易理解一次執(zhí)行一個 section 代碼塊
  if (gomp_iter_dynamic_next (&s, &e))
    ret = s;
  else
    ret = 0;
  return ret;
}
// 下面是部分 gomp_sections_init 的代碼
static inline void
gomp_sections_init (struct gomp_work_share *ws, unsigned count)
{
  ws->sched = GFS_DYNAMIC;
  ws->chunk_size = 1; // 設(shè)置 chunk size 等于 1
  ws->end = count + 1L; // 因為一共有 count 個 section 塊
  ws->incr = 1; // 每次增長一個
  ws->next = 1; // 從 1 開始進(jìn)行 chunk size 的分配 因為 0 表示退出循環(huán)(編譯器角度分析)
}
unsigned
GOMP_sections_next (void)
{
  // 這個函數(shù)就比較容易理解了 就是獲取一個 chunk 拿到對應(yīng)的 section 的執(zhí)行權(quán)
  long s, e, ret;
  if (gomp_iter_dynamic_next (&s, &e))
    ret = s;
  else
    ret = 0;
  return ret;
}
// 下面的函數(shù)在之前的很多文章當(dāng)中都分析過了 這里不再進(jìn)行分析
// 下面的函數(shù)的主要過程就是使用 CAS 指令不斷的進(jìn)行嘗試,直到獲取成功或者全部獲取完成 沒有 chunk 需要分配
bool
gomp_iter_dynamic_next (long *pstart, long *pend)
{
  struct gomp_thread *thr = gomp_thread ();
  struct gomp_work_share *ws = thr->ts.work_share;
  long start, end, nend, chunk, incr;
  end = ws->end;
  incr = ws->incr;
  chunk = ws->chunk_size;
  if (__builtin_expect (ws->mode, 1))
    {
      long tmp = __sync_fetch_and_add (&ws->next, chunk);
      if (incr > 0)
  {
    if (tmp >= end)
      return false;
    nend = tmp + chunk;
    if (nend > end)
      nend = end;
    *pstart = tmp;
    *pend = nend;
    return true;
  }
      else
  {
    if (tmp <= end)
      return false;
    nend = tmp + chunk;
    if (nend < end)
      nend = end;
    *pstart = tmp;
    *pend = nend;
    return true;
  }
    }
  start = ws->next;
  while (1)
    {
      long left = end - start;
      long tmp;
      if (start == end)
  return false;
      if (incr < 0)
  {
    if (chunk < left)
      chunk = left;
  }
      else
  {
    if (chunk > left)
      chunk = left;
  }
      nend = start + chunk;
      tmp = __sync_val_compare_and_swap (&ws->next, start, nend);
      if (__builtin_expect (tmp == start, 1))
  break;
      start = tmp;
    }
  *pstart = start;
  *pend = nend;
  return true;
}

以上就是“OPENMP SECTIONS CONSTRUCT原理是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI