Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么std::for_each比u_gnu_parallel::for_each快_C++_Parallel Processing_Stl - Fatal编程技术网

C++ 为什么std::for_each比u_gnu_parallel::for_each快

C++ 为什么std::for_each比u_gnu_parallel::for_each快,c++,parallel-processing,stl,C++,Parallel Processing,Stl,我试图理解为什么在单线程上运行的std::for_each比下面示例中的u_gnu_并行::for_each快约3倍: Time =0.478101 milliseconds vs 下面是我用来进行基准测试的代码: #include <iostream> #include <chrono> #include <parallel/algorithm> //The struct I'm using for timming struct TimerAvrg

我试图理解为什么在单线程上运行的std::for_each比下面示例中的u_gnu_并行::for_each快约3倍:

Time =0.478101 milliseconds
vs

下面是我用来进行基准测试的代码:

#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;
}
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;
我已经检查了好几篇帖子,但要么很老,要么不是同一个问题

我的问题是:

为什么并行运行速度较慢

我使用了错误的函数

在这篇文章中,我的意思是,不支持带有标准化并行性TS的gcc,表中用红色表示,我的代码是并行运行的

您的函数[]auto v{v=0;}非常简单

该函数可以用对memset的一次调用或使用SIMD指令进行单线程并行化来代替。如果知道它会覆盖与向量最初具有的相同状态,则可以优化整个循环。对于Optimizer来说,替换std::for_可能比并行实现更容易

此外,假设并行循环使用线程,则必须记住,在这种情况下,创建和最终同步不需要在处理过程中进行同步,这会产生开销,这对于您的琐碎操作可能非常重要


线程并行通常只适合于计算量大的任务。v=0是计算成本最低的操作之一。

您的基准测试有问题,我甚至惊讶于运行它需要时间

你写道: std::对于_eachv.begin,v.end,[]自动v{v=0;}

由于v是运算符的一个局部参数,没有读取,所以我希望编译器会删除它。 由于现在有一个带有主体的循环,因此可以移除该循环,并且没有可观察的效果。 与此类似,向量可以被移除,因为你没有任何读卡器

因此,在没有任何副作用的情况下,这一切都可以消除。如果您使用并行算法,很可能会有某种同步,这使得优化此算法变得更加困难,因为在另一个线程中可能会有副作用?证明它不是更复杂,更不用说线程管理可能存在的副作用了


为了解决这个问题,许多基准测试都在宏中安装了卡车,以迫使编译器承担副作用。在lambda中使用它们,这样编译器就不会删除它。

注意,这不是C++17的官方并行库。它在文件中说:这个文件是标准C++库的GNU扩展。你能显示使用Syd的代码吗?:FoY.My:Std::Frach可能被优化到一个简单的循环,使用SIMD指令。循环可能太短,不能并行使用。创建线程和连接线程的成本是一样的。@NathanOliver完全一样只要用_gnu_parallel::替换std::这就是我每次更改的全部内容如果它被删除,我想不会有那么多时间~0.478101 ms,但它经过了很好的优化,看起来什么都没做是的,我想你是对的。。timming比实现lambda更适合于并行化,这是非常好的优化
g++ -std=c++17 -fomit-frame-pointer -Ofast -march=native -ffast-math -mmmx -msse -msse2 -msse3 -DNDEBUG -Wall -fopenmp benchmark.cpp -o benchmark 
/usr/include/c++/8/tr1/cmath:1163:20: error: ‘__gnu_cxx::conf_hypergf’ has not been declared
   using __gnu_cxx::conf_hypergf;