2013-10-05 40 views
0

我在使用gcc 4.7.2在openSUSE Linux的下面的代碼的結果感到驚訝:是std :: packaged_task真的很貴嗎?

#include <cmath> 
#include <chrono> 
#include <cstdlib> 
#include <vector> 
#include <chrono> 
#include <iostream> 
#include <future> 

int main(void) 
{ 
    const long N = 10*1000*1000; 
    std::vector<double> array(N); 
    for (auto& i : array) 
    i = rand()/333.; 

    std::chrono::time_point<std::chrono::system_clock> start, end; 
    start = std::chrono::system_clock::now(); 
    for (auto& i : array) 
    pow(i,i); 
    end = std::chrono::system_clock::now(); 
    std::chrono::duration<double> elapsed_seconds = end-start; 
    std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n"; 

    start = std::chrono::system_clock::now(); 
    for (auto& i : array) 
    std::packaged_task<double(double,double)> myTask(pow); 
    elapsed_seconds = std::chrono::system_clock::now()-start; 
    std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n"; 

    start = std::chrono::system_clock::now(); 
    for (auto& i : array) 
    std::packaged_task<double()> myTask(std::bind(pow,i,i)); 
    elapsed_seconds = std::chrono::system_clock::now()-start; 
    std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n"; 

    return 0; 
} 

結果是這樣的(並且是運行之間相當一致):

elapsed time: 0.694315s 
elapsed time: 6.49907s 
elapsed time: 8.42619s 

如果我正確地解釋結果,只是創建一個std::packaged_task(甚至沒有執行它或存儲它的參數尚未)已經是十倍高於executingpow更加昂貴。這是一個有效的結論嗎?

這是爲什麼?

這是偶然的海灣合作委員會的具體?

+2

嘛,自然,包裝任務包含同步原語,是昂貴的 - 總線鎖定和管道沖洗都是低層次的同步原語的共同後果,所以單線程同步總是會失去針對單線程的非同步。您必須真正能夠從並行或並行執行中受益,才能使並行解決方案成爲可行的改進。 –

+0

(你可以建立你自己的打包任務[帶有承諾](http://stackoverflow.com/q/11004273/596781)。單單承諾包含一些嚴重的同步機制。) –

+0

@KerrekSB,如果創建一個packaged_task需要使用多個鎖定基元。畢竟,沒有可能的爭論(尚)。創建這麼多的互斥鎖只需要0.09s - 所以除非你需要爲每個packaged_task創建10個互斥鎖,還是有很大的空間... –

回答

1

你是不是一個定時的packaged_task的執行,只有它的創造。

std::packaged_task<double(double,double)> myTask(pow); 

這不會執行myTask,只會創建它。理想情況下,你不應該測量這個,你應該測量myTask(i, i),我通過改變你的程序到以下(我刪除了測量std::bind)。

結果比你測得更糟的是:

timing raw 
elapsed time: 0.578244s 

timing ptask 
elapsed time: 20.7379s 

我猜packaged_task s爲不適合重複的小任務,開銷肯定比任務本身更大。我對此的看法是,您應該將它們用於多任務代碼,這需要比調用和同步packaged_task所花費的時間更長的任務。

如果你沒有多任務,我覺得有一個在包裝類中準備與同步原語的多線程函數調用沒有意義的,他們是不是免費的,可悲的。

爲了記錄在案,這裏是我用什麼:

#include <cmath> 
#include <chrono> 
#include <cstdlib> 
#include <vector> 
#include <chrono> 
#include <iostream> 
#include <future> 
#include <thread> 

int main(void) 
{ 
    const long N = 10*1000*1000; 
    std::vector<double> array(N); 
    for (auto& i : array) 
    i = rand()/333.; 

    std::cout << "timing raw" << std::endl; 
    std::chrono::time_point<std::chrono::system_clock> start, end; 
    start = std::chrono::system_clock::now(); 
    for (auto& i : array) 
    pow(i,i); 
    end = std::chrono::system_clock::now(); 
    std::chrono::duration<double> elapsed_seconds = end-start; 
    std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n\n"; 

    std::cout << "timing ptask" << std::endl; 
    start = std::chrono::system_clock::now(); 
    std::packaged_task<double(double,double)> myTask(pow); 
    for (auto& i : array) 
    { 
     myTask(i, i); 
     myTask.get_future().wait(); 
     myTask.reset(); 
    } 
    elapsed_seconds = std::chrono::system_clock::now()-start; 
    std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n\n"; 
    return 0; 
} 
+1

嗨@Leonardo,謝謝你的詳盡答案。我認爲你會得出這樣的結論:創建packaged_task代價昂貴 - 使用它將工作轉移到其他內核僅適用於大量工作。 –