CodeHighlight

2013年8月31日 星期六

[C++] Thread Function相關測試

因為研究測試資料莫名的大,在生成資料的過程中,常常會有需要長時間等待的狀況,
這時就會想到當初課堂說的平行化處理,所以想說用thread來榨乾CPU的效能呀~

很幸運的是,在C++ 11之後,已經把thread列入標準凾式庫內了,
雖然早期的Compiler沒有支援,不過如果用IDE有乖乖升級的話,
應該之後的版本都會把這東西補進去
所以可以把那精美的pthread先放在一旁(pthread你好難懂呀~)

小弟在這邊個環境是在ubuntu上面,gcc version 4.4.3,
(真的比較習慣用vim寫code,直接上server跑資料也比較方便)

在使用上,編譯需要加上相關參數:
g++ source.cpp -std=c++0x -lpthread -Os -o ./target

  1. -std=c++0x:指定編譯的C++版本
  2. -lpthread:引入thread的lib,是說也看到有-pthread的,目前測過兩個都可以


在程式碼內,需要引入「thread」的函式:#include <thread>
這樣就可以呼叫thread相關函式來奴役充分利用CPU的資源了

在使用上,根據不同情境,使用的狀況會有所不同:

  1. 在main呼叫一般function

    這應該是最容易理解的,根據cplusplus.com的範例,他的程式碼長這個樣子:

    // thread example
    #include <iostream>       // std::cout
    #include <thread>         // std::thread
     
    void foo() 
    {
      // do stuff...
    }
    
    void bar(int x)
    {
      // do stuff...
    }
    
    int main() 
    {
      std::thread first (foo);     // 開新thread:「first」執行「foo」函式
      std::thread second (bar,0);  // 開新thread:「second」執行「bar」函式,傳入參數0
    
      std::cout << "main, foo and bar now execute concurrently...\n";
    
      // synchronize threads:
      first.join();                // 等「first」thread執行結束
      second.join();               // 等「second」thread執行結束
    
      std::cout << "foo and bar completed.\n";
    
      return 0;
    }
    因為C++ 11 thread已經將這個功能物件化,所以使用上就和使用一般物件一樣,
    先生成一個物件,然後將要分工執行的function和參數傳進去,這時候main function就只要等待執行結束在收割結果就好啦!

  2. 在class內呼叫同個class內的member function

    不過有時候,我們會需要在class裡面,針對特定的工作進行加速,像是某些需要大量重複計算又互不干擾的函式,這時候就會對單一個member function做thread加速,那這時得使用會變成:

    #include <iostream>
    #include <thread>
    
    using namespace std;
    
    ClassA::ClassA(){
    
    // do stuff...
    } void ClassA::memberFunA(int a){
    // do stuff...
    } void ClassA::memberFunB(){
    std::thread first (&ClassA::memberFunA, this, 0);
    first.join(); 
    // do stuff...
    }
    以上面為例,memberFunB需要呼叫同一個class的memberFunA,因此需要引入member function的完整reference,並且第一個參數要代入是自己這個class,讓thread可以正確找到要引入的資料為何。
  3. 在main呼叫特定物件的member function

    另一個情況是:在main function中需要將某些物件放到thread裡面做平行化運算:

    #include <iostream>
    #include <thread>
    using namespace std;
    
    int main( int argc, char** argv )
    {
          ClassA object1;
    
    std::thread first (&ClassA::memberFunA, &object1, 0);
    first.join(); 
    }
    在這邊的想法和2.類似:引入的function需要指定class和member function的reference,加上由於是用物件形式呼叫member function,因此需要在指定該物件的reference,才可以存取該物件內的member function
不過要注意的是,在引入物件進去thread平行化執行時,是將整個函式和變數複製一份到thread使用,因此如果有需要保留修改變數的狀況的話(EX: 引入一個陣列,裡面存修改後的狀況,讓多個thread個別修改一段),則需要加上「std::ref()」來處理。

以上大概就是C++裡面thread的基本使用,其實還有很多像是針對執行中thread的操作啦,thread間的溝通之類的東西,不過目前小弟還用不到那麼進階的功能,所以在這邊就先不提啦,之後有機會的話會再補上去。

Reference:

沒有留言:

張貼留言