簡體   English   中英

為什么std :: for_each比__gnu_parallel :: for_each快

[英]Why std::for_each is faster than __gnu_parallel::for_each

我試圖理解為什么在以下示例中在單線程上運行的std::for_each__gnu_parallel::for_each~3倍:

Time =0.478101 milliseconds

Time =0.166421 milliseconds

這是我用來基准測試的代碼:

#include <iostream>
#include <chrono>
#include <parallel/algorithm>

//The struct I'm using for timming
struct   TimerAvrg
{
    std::vector<double> times;
    size_t curr=0,n;
    std::chrono::high_resolution_clock::time_point begin,end;
    TimerAvrg(int _n=30)
    {
        n=_n;
        times.reserve(n);
    }

    inline void start()
    {
        begin= std::chrono::high_resolution_clock::now();
    }

    inline void stop()
    {
        end= std::chrono::high_resolution_clock::now();
        double duration=double(std::chrono::duration_cast<std::chrono::microseconds>(end-begin).count())*1e-6;
        if ( times.size()<n)
            times.push_back(duration);
        else{
            times[curr]=duration;
            curr++;
            if (curr>=times.size()) curr=0;}
    }

    double getAvrg()
    {
        double sum=0;
        for(auto t:times)
            sum+=t;
        return sum/double(times.size());
    }
};



int main( int argc, char** argv )
{
    float sum=0;
    for(int alpha = 0; alpha <5000; alpha++)
    {
        TimerAvrg Fps;
        Fps.start();
        std::vector<float> v(1000000);
        std::for_each(v.begin(), v.end(),[](auto v){ v=0;});
        Fps.stop();
        sum = sum + Fps.getAvrg()*1000;
    }

    std::cout << "\rTime =" << sum/5000<< " milliseconds" << std::endl;
    return 0;
}

這是我的配置:

gcc version 7.3.0 (Ubuntu 7.3.0-21ubuntu1~16.04) 

Intel® Core™ i7-7600U CPU @ 2.80GHz × 4

htop檢查程序是否在單線程或多線程中運行

g++ -std=c++17 -fomit-frame-pointer -Ofast -march=native -ffast-math -mmmx -msse -msse2 -msse3 -DNDEBUG -Wall -fopenmp benchmark.cpp -o benchmark 

gcc 8.1.0不會編譯相同的代碼。 我收到該錯誤消息:

/usr/include/c++/8/tr1/cmath:1163:20: error: ‘__gnu_cxx::conf_hypergf’ has not been declared
   using __gnu_cxx::conf_hypergf;

我已經檢查了幾個帖子,但是它們很舊或不一樣。

我的問題是:

為什么並行速度較慢?

我使用了錯誤的功能?

cppreference中,這表示不支持Standardization of Parallelism TS gcc(表中以紅色表示),並且我的代碼正在並行運行!

您的函數[](auto v){ v=0;} 非常簡單。

可以通過單次調用memset來替換該函數,也可以將SIMD指令用於單線程並行性。 知道它會覆蓋與向量最初相同的狀態,因此可以優化整個循環。 對於優化器來說,替換std::for_each比並行實現要容易。

此外,假設並行循環使用線程,則必須記住創建和最終同步(在這種情況下,在處理期間無需同步)會產生開銷,這對於您的瑣碎操作而言可能是很重要的。

線程並行性通常僅在計算量大的任務上值得。 v=0是存在的計算成本最低的操作之一。

您的基准測試是有缺陷的,我什至感到驚訝,它需要時間來運行。

您寫道:std :: for_each(v.begin(),v.end(),[](auto v){v = 0;});

由於voperator()的局部參數,沒有任何讀取,所以我希望它會被編譯器刪除。 由於您現在有了一個帶有主體的循環,因此可以除去該循環,並且沒有明顯的效果。 與此類似,矢量也可以刪除,因為您沒有任何閱讀器。

因此,沒有任何副作用,可以將其全部消除。 如果您將使用並行算法,那么您可能會有某種同步,這會使優化變得更加困難,因為另一個線程可能會有副作用? 證明它並不更復雜,更不用說可能存在的線程管理的副作用了?

為了解決這個問題,許多基准測試都在宏程序中添加了一些條件,以迫使編譯器承擔副作用。 在lambda中使用它們,以便編譯器不會將其刪除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM