OPENMP FOR CONSTRUCT GUIDED 排程方式實現原理和原始碼分析

2023-02-15 06:00:29

OPENMP FOR CONSTRUCT GUIDED 排程方式實現原理和原始碼分析

前言

在本篇文章當中主要給大家介紹在 OpenMP 當中 guided 排程方式的實現原理。這個排程方式其實和 dynamic 排程方式非常相似的,從編譯器角度來說基本上是一樣的,在本篇文章當中就不介紹一些相關的必備知識了,如果不瞭解可以先看這篇文章 OpenMP For Construct dynamic 排程方式實現原理和原始碼分析

GUIDED 排程方式分析

我們使用下面的程式碼來分析一下 guided 排程的情況下整個程式的執行流程是怎麼樣的:

#pragma omp parallel for num_threads(t) schedule(guided, size)
for (i = lb; i <= ub; i++)
  body;

編譯器會將上面的程式編譯成下面的形式:

void subfunction (void *data)
{
  long _s0, _e0;
  while (GOMP_loop_guided_next (&_s0, &_e0))
  {
    long _e1 = _e0, i;
    for (i = _s0; i < _e1; i++)
      body;
  }
  // GOMP_loop_end_nowait 這個函數的主要作用就是釋放資料的記憶體空間 在後文當中不進行分析
  GOMP_loop_end_nowait ();
}
​
GOMP_parallel_loop_guided_start (subfunction, NULL, t, lb, ub+1, 1, size);
subfunction (NULL);
// 這個函數在前面的很多文章已經分析過 本文也不在進行分析
GOMP_parallel_end ();

根據上面的程式碼可以知道,上面的程式碼當中最主要的兩個函數就是 GOMP_parallel_loop_guided_start 和 GOMP_loop_guided_next,現在我們來分析一下他們的原始碼:

  • GOMP_parallel_loop_guided_start
void
GOMP_parallel_loop_guided_start (void (*fn) (void *), void *data,
         unsigned num_threads, long start, long end,
         long incr, long chunk_size)
{
  gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
          GFS_GUIDED, chunk_size);
}
​
static void
gomp_parallel_loop_start (void (*fn) (void *), void *data,
        unsigned num_threads, long start, long end,
        long incr, enum gomp_schedule_type sched,
        long chunk_size)
{
  struct gomp_team *team;
  // 解析到底啟動幾個執行緒執行並行域的程式碼
  num_threads = gomp_resolve_num_threads (num_threads, 0);
  // 建立執行緒組
  team = gomp_new_team (num_threads);
  // 對共用資料進行初始化操作
  gomp_loop_init (&team->work_shares[0], start, end, incr, sched, chunk_size);
  // 啟動執行緒組執行函數 fn
  gomp_team_start (fn, data, num_threads, team);
}
​

在上面的程式當中 GOMP_parallel_loop_guided_start,有 7 個引數,我們接下來仔細解釋一下這七個引數的含義:

  • fn,函數指標也就是並行域被編譯之後的函數。
  • data,指向共用或者私有的資料,在並行域當中可能會使用外部的一些變數。
  • num_threads,並行域當中指定啟動執行緒的個數。
  • start,for 迴圈迭代的初始值,比如 for(int i = 0;