Home People Research Blog Courses Links Search Download
NCHC

Blog

Blog 最新文章

  1. Visual Studio 的遠端偵錯:Windows
    2021/03/24 14:45
  2. Visual Studio 2019 16.9 支援使用 OpenMP LLVM
    2021/03/03 13:52
  3. Valve 推出完全支援 OpenXR 的 SteamVR 1.16.8
    2021/02/25 09:43

Blog 最新回應

  1. 加入斜體文字...
    2021/02/07 21:06
  2. 加入斜體文字...
    2021/02/07 21:06
  3. 加入斜體文字...
    2021/02/07 21:06

Keyword 關鍵字

PHP xml GitLab C++17 CUDA OpenCV Pandas 開放資料 Qt Docker svn HoloLens 2 OpenMP Oculus Rift S Oculus ASUS Xtion iFlyover 3d print WebGL Vulkan OpenCL OpenNI Java 資料視覺化 Windows MR NiTE2 OpenXR Oculus Quest 2 HTC Vive OpenVR Pandas C++ Boost 3D立體 C++14 C++20 Python OpenGL Valve Index javascript HTC Vive Focus MR git Python OpenNI2 C++14 C++11 VR CubeX Docker HTC Vive Pro 資訊地圖 Kinect VR 開放資料

類別:技術相關 » 技術研究
文章發表|我要回應|RSS訂閱

簡易的程式平行化-OpenMP(三)範例 parallel、section

本文原發表於:http://heresy.spaces.live.com/blog/cns!E0070FB8ECF9015F!1281.entry


OpenMP 裡,平行化的方式有三種:parallel、sections、for(不過 section 和 for 都需要 parrallel)。這裡,舉些例子來說明他們的運作。

而用來測試的函式 Test內容如下

void Test( int n )
{
printf( "<T:%d> - %d
", omp_get_thread_num(), n );
}

輸出的形式會是:<T:thread_id> - n。


parrallel

parrallel 的語法很直接,就是 #pragma omp parallel;不過原則上,後面要用 {} 來指定 scope。範例程式如下:

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
#pragma omp parallel
{
Test( 0 );
}
system( "pause" );
}

而這樣的程式在一台雙核心的電腦上,結果應該會是:

<t:0> - 0
<t:1> - 0

從結果可以看出來,Test() 被兩個不同的 thread 個別執行了一次,所以會輸出兩行;這是因為 OpenMP 會根據硬體,自動選擇預設的執行緒數目。

接著,在針對程式些修改,變成

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#define OMP 11

int main(int argc, char* argv[])
{
#pragma omp parallel if(OMP>10) num_threads(3)
{
Test( 0 );
}
printf( "
==========================

" );
system( "pause" );
}

而這樣的程式在一台雙核心的電腦上,結果應該會是:

<t:0> - 0
<t:2> - 0
<t:1> - 0

在程式中,加入了 if 和 num_threads 這兩個語法。num_threads 是用來指定執行緒的數目的,而在上面的程式中,把它指定成 3,所以結果會由三個不同的 thread,個別呼叫一次 Test() 。

而 if(OMP>10) 則是拿來控制是否要平行化的條件;如果把 #define OMP 11 改成 #define OMP 9 (或者任何不大於 10 的數)的話,結果就會變成 Test() 只被呼叫一次,只印出一行。不過要注意的一點是,用 if 條件來停止平行化,實際上應該是將執行緒的數目設定成 1;也就是說 OpenMP 還是會做處理,但是會只用一個執行緒跑。而這樣使用要注意的就是,如果曾經有因為 if 而停止平行化的話,接下來的預設的執行緒數目也會變成 1!所以如果真的要用 if 來判斷是否要平行化,最好把接下來的部份,加上 num_threads 來指定執行緒的數目。下面是一個例子:

#pragma omp parallel
Test( 1 );
#pragma omp parallel if(false)
Test( 2 );
#pragma omp parallel
Test( 3 );

他的執行結果應該會是:

<t:0> - 1
<t:1> - 1
<t:0> - 2
<t:0> - 3

這是因為在執行 Test(1) 的時候,有被平行化成兩個 thread,所以被執行了兩次。但是到了 Test(2) 的時候,因為執行了 if(false),所以將平行化關閉、設定為一個 thread;同時這也導致了接下來的 Test(3) 也變成只以一個 thread 來進行。

而在 parallel 的範圍內,還有一些 directive 是可以使用的;像是 single、master 等等。像下面的程式

#pragma omp parallel num_threads(2)
{
for( int i = 0; i < 3; i )
Test( i );
printf( "Hi
" );
#pragma omp single
{
printf( "Hi, single
" );
}
#pragma omp master
printf( "Hi, master
" );
}

執行結果:

<t:0> - 0
<t:1> - 0
<t:0> - 1
<t:1> - 1
<t:0> - 2
<t:1> - 2
Hi
Hi
Hi, single
Hi, master

其中,可以發現加上 single 和 master 的部份的程式只會被執行一次;而 master 和 single 兩者間的差異,則是 master 會一定由主執行緒來執行,single 不一定。

基本上,Heresy 不大確定什麼時候會直接用到 parrallel,所以也就不多加著墨了。(什麼時候會要把一般的程式多執行幾次啊? @@)


sections

sections 的用處,是把程式中沒有相關性的各個程式利用 #pragma omp section 來做區塊切割,然後由 OpenMP 做平行的處理。下面的程式是一個簡單的例子:

int main(int argc, char* argv[])
{
#pragma omp parallel sections
{
#pragma omp section
{
for( int k = 0; k < 100000; k )
{}
Test( 0 );
}
#pragma omp section
{
Test( 1 );
}
#pragma omp section
{
Test( 2 );
}
#pragma omp section
{
Test( 3 );
}
}
}

而執行出來的結果,則是:

<T:1> - 1
<T:1> - 2
<T:1> - 3
<T:0> - 0

從執行的輸出結果可以發現:由於 thread0 先執行了執行時間最久的第一個 section,而在 thread0 結束第一個 section 前,其他三個 section 已經由 thread1 執行結束了∼

不過利用 sections 平行化的時候,要注意程式的相依性;如果兩段程式是有相關性的話,實際上並不適合用 sections 來做平行化。下面是個錯誤的例子:

int	a[5];
#pragma omp parallel sections
{
#pragma omp section
{
int k;
for( int i = 0; i < 5; i )
{
a[i] = i;
for( k = 0; k < 10000; k )
{}
}
}
#pragma omp section
{
for( int i = 0; i < 5; i )
printf( "%d
", a[i] );
}
}

其中,程式裡 for( k = 0; k < 10000; k ){} 的目的只是在拖慢時間。輸出結果是:

0
1
-858993460
-858993460
-858993460

這是因為第一個 section 的部份,執行的速度比較慢,所以當第二的 section 要列印的時候,還來不及將資料填入 a[] 裡,所以會導致錯誤。


目錄:

  • 簡易的程式平行化方法-OpenMP(一)簡介
  • 簡易的程式平行化-OpenMP(二)語法說明
  • 簡易的程式平行化-OpenMP(三)範例 parallel、section
  • 簡易的程式平行化-OpenMP(四) 範例 for
  • 簡易的程式平行化-OpenMP(五) 變數的平行化

參考資料:

  • MSDN 的 OpenMP:http://msdn2.microsoft.com/en-us/library/tt15eb9t.aspx

張貼者:heresy於2007/05/04 10:31 上午有0則回應,瀏覽次數:7,436次

-- TOP --

我要回應
* 身份  訪客 (暱稱:)
 本篇文章作者 (帳號:密碼:)
* 內容      
很高興 悲傷 震驚 疑惑 大笑 發瘋 傷心
* 留言密碼 (請輸入下方圖片中去除前、後位數的數字,共五碼。)
說明 1. * 表示必填欄位。
2. 不支援HTML Tag。
   

-- TOP --

© Visualization and Interactive Media Laboratory of NCHC, 2007 - 2021, All Rights Reserved. Contact E-mail