Heresy's profile[Heresy' Space]PhotosBlogListsMore Tools Help
    6/9/2006

    簡易的程式平行化方法-OpenMP(一)簡介

    嗯~首先,Heresy 也是最近才開始試著用 openMP 的,所以其是這篇與其說是教學或介紹,倒不如說是學習心得會更為恰當。會不會繼續用?說實話也是未知數。總之,看著辦囉~

    也希望有人對這東西有研究的話,能多多指教。


    多執行緒的概念

    目前雙核心的 CPU 當道,AMD 的 Athlon64x2、Intel 的 Pentium-D、Core Duo,以及即將上市的 Core 2 Duo,儼然將成為下一代電腦的主流(尤其是超低價的 Pentium D,絕對是現階段 C/P 值極高的雙核心 CPU)。但是雙核心有什麼用呢?

    對於一般單一執行緒(single thread)的程式,多核心的處理器並沒有辦法提升它的處理效能;不過對於多執行緒(multi thread)的程式,就可以透過不同的核心同時計算,來達到加速的目的了!簡單的例子,以單執行緒的程式來說,一件事做一次要十秒的話,要做十次,都丟給同一顆核心做的話,自然就是 10 秒 * 10 次,也就是 100 秒了;但是以多執行緒的程式來說,它可以把這一件事,分給兩顆核心各自做,每顆核心各做 5 次,所以所需要的時間就只需要 50 秒!

    當然,多執行緒的程式實際上沒這麼簡單。在工作的切割、結合上,也是要多花時間的,所以在現實中,即使最佳狀況,雙核心的效能也不會是 1 + 1 = 2 這樣的理想化。除此之外,也不是所有工作都是可以切割的!很多工作是有關聯性的,這樣如果直接切割給不同的處理核心各自去平行運算,出來的結果是肯定有問題的。而且,多執行緒的程式在編寫、維護上,也都比單一執行緒的程式複雜上不少。

    不過,如果電腦本身是多處理器、多核心處理器,或是處理器擁有像 Intel Hyper-Threading Technology 這類的能在同一個時間處理多個執行緒的功能的話,那把各自獨立的工作由單一執行緒改成多執行緒,在執行的效率上,大多還是會有增進的!


    多執行緒的程式

    寫程式的時候該怎麼去寫多執行緒的程式呢?一般的方法,就是真的利用 thread 的控制,去實際在程式中去產生其他的 thread 來處理。像 POSIX Threads 這套 library,就是用來產生、控制執行緒的函式庫。而像 Microsoft VisualStudio 2005 中,也有提供控制 thread 的功能。這種方法,大多就是產生多個 thread,而再由主要的 thread 把工作拆開,分給各 thread 去運算,最後再由主要的 thread 回收結果、整合。

    但是,實際上要去控制 thread 是滿麻煩的~在程式的編寫上,也會複雜不少;而如果我們只是想要把一些簡單的迴圈平行化處理,用 thread library 來控制,實在有點殺雞用牛刀的感覺。這時候,用 Open MP 就簡單多了!OpenMP 是一種能透過高階指令,很簡單地將程式平行化、多執行緒化的 API;在最簡單的情形,甚至可以只加一行指令,就可以將迴圈內的程式平行化處理了!


    OpenMP 的基本使用

    要在 Visual C++ 2005 中使用 openMP 其實不難,只要將 Project 的 Properties 中 C/C++ 裡 Language 的 OpenMP Support 開啟(參數為 /openmp),就可以讓 VC++2005 在編譯時支援 OpenMP 的語法了;而在使用到 OpenMP 的檔案,則需要先 include OpenMP 的 header file : omp.h。

    而要將 for 迴圈平行化處理,該怎麼做呢?非常簡單,只要在前面加上一行

    #pragma omp parallel for
    就夠了!

    也可以實際用一段簡單的程式,來弄清楚它的運作方式。

    #include <STDIO.H>
    #include <STDLIB.H>
    
    void Test( int n )
    {
     for( int i = 0; i < 10000; ++ i )
     {
      //do nothing, just waste time
     }
     printf( "%d, ", n );
    }
    
    int main(int argc, char* argv[])
    {
     for( int i = 0; i < 10; ++ i )
      Test( i );
    
     system( "pause" );
    }

    上面的程式,在 main() 是一個很簡單的迴圈,跑十次,每次都會呼叫 Test() 這個函氏,並把是迴圈的執行次數(i)傳進 Test()  並列印出來。想當然耳,它的結果會是:

    0, 1, 2, 3, 4, 5, 6, 7, 8, 9,

    而如果想利用 OpenMP 把 mian() 裡面的迴圈平行化處理呢?只需要修改成下面的樣子:

    #include <omp.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    void Test( int n )
    {
     for( int i = 0; i < 10000; ++ i )
     {
      //do nothing, just waste time
     }
     printf( "%d, ", n );
    }
    
    int main(int argc, char* argv[])
    {
     #pragma omp parallel for
     for( int i = 0; i < 10; ++ i )
      Test( i );
    
     system( "pause" );
    }

    夠簡單吧?重頭到尾,只加了兩行(紅色部分)!而執行後,可以發現結果也變了!

    0, 5, 1, 6, 2, 7, 3, 8, 4, 9,

    可以從結果很明顯的發現,他沒有照著 0 到 9 的順序跑了!而上面的順序怎麼來的?其實很簡單,OpenMP 只是把迴圈 0 - 9 共十個步驟,拆成 0 - 4, 5 - 9 兩部份,丟給不同的執行緒去跑,所以數字才會出現這樣交錯性的輸出~

    而要怎麼確定真的有跑多執行緒呢?如果本來有多處理器、多核心處理器或有 Hyper Thread 的話,一個單執行緒程式,最多只會把一顆核心的使用量吃完;像比如說在 Pentium 4 HT 上跑,單一執行緒的程式,在工作管理員中看到的 CPU 使用率最多就是 50%。而利用 OpenMP 把回圈進行平行化處理後,就可以在執行廻圈時,把兩顆核心的 CPU 都榨光了!也就是工作管理員可以看到 CPU 使用率是 100%。


    當然,OpenMP 不是只有這個指令的~而且 OpenMP 也不適用於任何場合。請期待第二部份。 :p

    不過理論上,應該會等測試過效率後,來列一些效能測試的結果。同時,會加一些錯誤利用 OpenMP 的示範。


    註:

    1. Microsoft VisualStudio 2005 Express 版中,並沒有附上 OpenMP 這個 library,似乎是要 Professional 以上版本才有(http://msdn2.microsoft.com/en-us/library/hs24szh9(VS.80).aspx)。
    2. OpenMP 官方網站:http://www.openmp.org
    3. OpenMP in Visual C++ (Microsoft MSDN Library):http://msdn2.microsoft.com/en-us/library/tt15eb9t.aspx
    4. Visual C++ 編譯器選項 /openmp:http://msdn2.microsoft.com/zh-tw/library/fw509c3b.aspx

     目錄:

    Comments (17)

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    Heresy Kwrote:
    感謝告知。
    不過,好像也習慣了… orz
    Apr. 15
    Rick Juangwrote:
    Heresy大的文章好像被偷了 http://g9677602.blogspot.com/2009/03/openmp.html
    Apr. 15
    Heresy Kwrote:
    你這樣的程式會有問題喔~
    這個叫做 race conditions,在平行化的演算法哩,如果要在不同的執行緒對同一個變數做修改的話,很有可能會產生試圖同時修改的問題。以這個情形,應該是要用 OpenMP 的 reduction 來解。
     
    至於時間問題,其實是你在迴圈內所做的事太少了;在這種情形下,平行化所需的額外負擔,甚至有可能比平行化的效能增益還少…導致效率不好。
    July 22
    Xeon Freemanwrote:
    我用了以下程式做測試
    **************************
    #include<iostream>
    #include <omp.h>
    using namespace std;

    int main()
    {
        int ta = 0,tb = 0;
        #pragma omp parallel for
        for(int i = 0; i < 2147483646; i++)
        {
            ta += 1;   
        }
        #pragma omp parallel for
        for(int i = 0; i < 2147483646; i++)
        {
            tb += 1;   
        }
       
        int tc = ta + tb;
        cout << tc;
       
        return 0;

    }
    *****************************
    是超到了2科CPU都100%沒錯
    但是出來的值用平行算法不是-4,甚至答案不同
    我猜是其中一個迴圈結束的時候另一個還沒結束
    所以不是ta跟tb都是2147483646
    但是.我比較總運算時間應該要是1/2阿
    但是奇怪的是運算時間沒有減少
    這讓小弟不解

    July 22
    Heresy Kwrote:
    一個方法是,你可以把這個路徑加入到系統環境變數的 path 裡;或者是把這個 dll 檔複製到執行檔所在目錄或者 windows\system32 目錄。
    這樣都可以讓程式執行時能抓到這個檔案。
     
    不過理論上正常安裝 VisualStudio 2005 Pro 應該不會有這個問題才對…
    Jan. 31
    Picture of Anonymous
    黑雨天白鋼琴 wrote:
    我發現我那個路徑有vcompd.dll檔..那怎麼會出現那種錯誤訊息呢..我使用的Visual Stdio是學校的授權版, 我昨天去抓Inte的complier,再配合VC居然就可以了,只不過只有30天授權,所以還是希望VC能跑..l謝謝
    Jan. 31
    Heresy Kwrote:
    理論上 VisualStudio 2005 的專業版應該是有支援 OpenMP 的
    或許可以先試著在 VisualStudio 的安裝目錄下,搜尋看看能不能找到這個檔案?
     
    以 Heresy 的電腦來說,這個檔案會在
    C:\Program Files (x86)\Microsoft Visual Studio 8\VC\redist\Debug_NonRedist\x86\Microsoft.VC80.DebugOpenMP
    Jan. 31
    Picture of Anonymous
    黑雨天白鋼琴 wrote:
    請問,我使用的是Microsoft Visual C++ 2005 中文pro版(Microsoft Visual Studio 2005,我會出現錯誤""這個應用程式無法啟動,因為找不到 vcompd.dll,重新安裝應用程式可能可以解決這個問題。問題是我已經試過兩台電腦都不行,不知道這是什麼原因呢?
    Jan. 31
    Heresy Kwrote:
    其實理由滿簡單的,市場區隔。
    為了讓 Professional、Standard 甚至 Express 等各種版本有差異,來訂出不同的價格,所以會根據不同的定位,把部分的功能給屏蔽掉。
    不然如果免費的 Express 版的功能和其他版本都一樣,還有誰要花錢買呢? ^^"
    Oct. 22
    tentbenwrote:
    我抓完了 謝啦   但是我後來改灌另一個版本的pro版,就可以跑了,結果跟你寫的一樣,不過我就不知道為什麼換各版本就可以跑了,但是還是謝謝你的教學,很有用。
    Oct. 22
    Heresy Kwrote:

    根據微軟的網頁(http://msdn2.microsoft.com/en-us/library/hs24szh9(VS.80).aspx)看來,Standard 版是沒有 OpenMP 的 @@

    Oct. 22
    tentbenwrote:
    我的VC是standard版的,是不是應該會有omp.h這個header檔,因為我也照你的步驟打開支援openMP那個選項了,但是就是少了omp.h,請問問題是出在哪呢?
    Oct. 22
    Heresy Kwrote:
    to tentben
    不知道你的 VC 版本是哪一版?如果是 Express 版的話,事本來就沒有的。
    Oct. 21
    tentbenwrote:
    你好~想請教你的是我的VC2005沒有omp.h這個header檔,請問需要去哪裡下載嗎?或是你可以傳給我嗎?
    我的e-mail是tentben@hotmail.com
    Oct. 21
    July 30
    Heresy Kwrote:
    Heresy 自己沒有嘗試過,不過可能得要搭配其他編譯器。
    例如 Intel C++ compiler 。
    May 8
    後權 賴wrote:
    我可以請教你嗎?就是我已經用VC6.0來開發程式了,由於程式已經開發多年,並且由多人開發,我看到,你有敘述在VC2005上可以直接使用,不知VC6.0可否使用,如果沒有,請問有什麼方法可以在VC6.0上使用OpenMP,或者有其他的方式呢?謝謝
    May 7

    Trackbacks

    The trackback URL for this entry is:
    http://heresy.spaces.live.com/blog/cns!E0070FB8ECF9015F!1018.trak
    Weblogs that reference this entry
    • None