您好,登錄后才能下訂單哦!
今天小編給大家分享一下OPENMP SECTIONS CONSTRUCT原理是什么的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
在這一小節當中我們將從編譯器角度去分析編譯器會怎么處理 sections construct ,我們以下面的 sections construct 為例子,看看編譯器是如何處理 sections construct 的。
#pragma omp sections { #pragma omp section stmt1; #pragma omp section stmt2; #pragma omp section stmt3; }
上面的代碼會被編譯器轉換成下面的形式,其中 GOMP_sections_start 和 GOMP_sections_next 是并發安全的,他們都會返回一個數據表示第幾個 omp section 代碼塊,其中 GOMP_sections_start 的參數是表示有幾個 omp section 代碼塊,并且返回給線程一個整數表示線程需要執行第幾個 section 代碼塊,這兩個函數的意義不同的是在 GOMP_sections_start 當中會進行一些數據的初始化操作。當兩個函數返回 0 的時候表示所有的 section 都被執行完了,從而退出 for 循環。
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 ();
事實上在函數 GOMP_sections_start 和函數 GOMP_sections_next 當中調用的都是我們之前分析過的函數 gomp_iter_dynamic_next ,這個函數實際上就是讓線程始終原子指令去競爭數據塊(chunk),這個特點和 sections 需要完成的語意是相同的,只不過 sections 的塊大小(chunk size)都是等于 1 的,因為一個線程一次只能夠執行一個 section 代碼塊。
unsigned GOMP_sections_start (unsigned count) { // 參數 count 的含義就是表示一共有多少個 section 代碼塊 // 得到當線程的相關數據 struct gomp_thread *thr = gomp_thread (); long s, e, ret; // 進行數據的初始化操作 // 將數據的 chunk size 設置等于 1 // 分割 chunk size 的起始位置設置成 1 因為根據上面的代碼分析 0 表示退出循環 因此不能夠使用 0 作為分割的起始位置 if (gomp_work_share_start (false)) { // 這里傳入 count 作為參數的原因是需要設置 chunk 分配的最終位置 具體的源代碼在下方 gomp_sections_init (thr->ts.work_share, count); gomp_work_share_init_done (); } // 如果獲取到一個 section 的執行權 gomp_iter_dynamic_next 返回 true 否則返回 false // s 和 e 分別表示 chunk 的起始位置和終止位置 但是在 sections 當中需要注意的是所有的 chunk size 都等于 1 // 這也很容易理解一次執行一個 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; // 設置 chunk size 等于 1 ws->end = count + 1L; // 因為一共有 count 個 section 塊 ws->incr = 1; // 每次增長一個 ws->next = 1; // 從 1 開始進行 chunk size 的分配 因為 0 表示退出循環(編譯器角度分析) } unsigned GOMP_sections_next (void) { // 這個函數就比較容易理解了 就是獲取一個 chunk 拿到對應的 section 的執行權 long s, e, ret; if (gomp_iter_dynamic_next (&s, &e)) ret = s; else ret = 0; return ret; } // 下面的函數在之前的很多文章當中都分析過了 這里不再進行分析 // 下面的函數的主要過程就是使用 CAS 指令不斷的進行嘗試,直到獲取成功或者全部獲取完成 沒有 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原理是什么”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。