Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.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++ 多线程比无线程C++;_C++_Multithreading_Optimization_Openmp - Fatal编程技术网

C++ 多线程比无线程C++;

C++ 多线程比无线程C++;,c++,multithreading,optimization,openmp,C++,Multithreading,Optimization,Openmp,我是多线程编程的新手,我知道之前有人问过几个类似的问题,但是我想得到一个特定于我代码的答案 我有两个要循环的对象向量(v1和v2),根据它们是否满足某些条件,将这些对象添加到单个向量,如下所示: 非多线程情况 std::vector<hobj> validobjs; int length = 70; for(auto i = this->v1.begin(); i < this->v1.end() ;++i) { if( !(**i).get_Ignore

我是多线程编程的新手,我知道之前有人问过几个类似的问题,但是我想得到一个特定于我代码的答案

我有两个要循环的对象向量(v1和v2),根据它们是否满足某些条件,将这些对象添加到单个向量,如下所示:

非多线程情况

std::vector<hobj> validobjs;
int length = 70;

for(auto i = this->v1.begin(); i < this->v1.end() ;++i) {
    if( !(**i).get_IgnoreFlag() && !(**i).get_ErrorFlag() ) {
        hobj obj(*i, length);
        validobjs.push_back(hobj);
    }
}

for(auto j = this->v2.begin(); j < this->v2.end() ;++j) {
    if( !(**j).get_IgnoreFlag() && !(**j).get_ErrorFlag() ) {
        hobj obj(*j, length);
        validobjs.push_back(hobj);
    }
}
std::vector<hobj> validobjs;
int length = 70;

#pragma omp parallel
{
    std::vector<hobj> threaded1;   // Each thread has own local vector
    #pragma omp for nowait firstprivate(length)
    for(auto i = this->v1.begin(); i < this->v1.end() ;++i) {
        if( !(**i).get_IgnoreFlag() && !(**i).get_ErrorFlag() ) {
            hobj obj(*i, length);
            threaded1.push_back(obj);
        }
    }

    std::vector<hobj> threaded2;  // Each thread has own local vector
    #pragma omp for nowait firstprivate(length)
    for(auto j = this->v2.begin(); j < this->v2.end() ;++j) {
        if( !(**j).get_IgnoreFlag() && !(**j).get_ErrorFlag() ) {
            hobj obj(*j, length);
            threaded2.push_back(obj);
        }
    }

    #pragma omp critical  // Insert local vectors to main vector one thread at a time
    {
        validobjs.insert(validobjs.end(), threaded1.begin(), threaded1.end());
        validobjs.insert(validobjs.end(), threaded2.begin(), threaded2.end());
    }
}
std::vector validobjs;
整数长度=70;
对于(自动i=this->v1.begin();iv1.end();++i){
如果(!(**i.get_IgnoreFlag()&&(**i.get_ErrorFlag()){
hobj obj(*i,长度);
有效推回(hobj);
}
}
对于(自动j=this->v2.begin();jv2.end();++j){
如果(!(**j.get_IgnoreFlag()&&(**j.get_ErrorFlag()){
hobj obj(*j,长度);
有效推回(hobj);
}
}
多线程案例

std::vector<hobj> validobjs;
int length = 70;

for(auto i = this->v1.begin(); i < this->v1.end() ;++i) {
    if( !(**i).get_IgnoreFlag() && !(**i).get_ErrorFlag() ) {
        hobj obj(*i, length);
        validobjs.push_back(hobj);
    }
}

for(auto j = this->v2.begin(); j < this->v2.end() ;++j) {
    if( !(**j).get_IgnoreFlag() && !(**j).get_ErrorFlag() ) {
        hobj obj(*j, length);
        validobjs.push_back(hobj);
    }
}
std::vector<hobj> validobjs;
int length = 70;

#pragma omp parallel
{
    std::vector<hobj> threaded1;   // Each thread has own local vector
    #pragma omp for nowait firstprivate(length)
    for(auto i = this->v1.begin(); i < this->v1.end() ;++i) {
        if( !(**i).get_IgnoreFlag() && !(**i).get_ErrorFlag() ) {
            hobj obj(*i, length);
            threaded1.push_back(obj);
        }
    }

    std::vector<hobj> threaded2;  // Each thread has own local vector
    #pragma omp for nowait firstprivate(length)
    for(auto j = this->v2.begin(); j < this->v2.end() ;++j) {
        if( !(**j).get_IgnoreFlag() && !(**j).get_ErrorFlag() ) {
            hobj obj(*j, length);
            threaded2.push_back(obj);
        }
    }

    #pragma omp critical  // Insert local vectors to main vector one thread at a time
    {
        validobjs.insert(validobjs.end(), threaded1.begin(), threaded1.end());
        validobjs.insert(validobjs.end(), threaded2.begin(), threaded2.end());
    }
}
std::vector validobjs;
整数长度=70;
#pragma-omp并行
{
std::vector threaded1;//每个线程都有自己的本地向量
#nowait firstprivate的pragma omp(长度)
对于(自动i=this->v1.begin();iv1.end();++i){
如果(!(**i.get_IgnoreFlag()&&(**i.get_ErrorFlag()){
hobj obj(*i,长度);
螺纹1.推回(obj);
}
}
std::vector threaded2;//每个线程都有自己的本地向量
#nowait firstprivate的pragma omp(长度)
对于(自动j=this->v2.begin();jv2.end();++j){
如果(!(**j.get_IgnoreFlag()&&(**j.get_ErrorFlag()){
hobj obj(*j,长度);
螺纹2.推回(obj);
}
}
#pragma omp critical//将局部向量一次插入一个线程到主向量
{
插入(validobjs.end(),threaded1.begin(),threaded1.end());
插入(validobjs.end(),threaded2.begin(),threaded2.end());
}
}
在非多线程情况下,我执行操作所花费的总时间大约是多线程情况下的4倍(1.5秒vs 6秒)

我知道#pragma omp critical指令对性能有影响,但由于我事先不知道validobjs向量的大小,因此我无法依靠索引随机插入

因此,问题是:

1)这种操作适合多线程吗?

2)如果是1)-多线程代码看起来合理吗?

3)我能做些什么来提高性能,使其比无线程的情况更快吗?

其他信息:

  • 上面的代码嵌套在一个更大的代码库中,该代码库执行10000-100000次迭代(此循环不使用多线程)。我知道生成线程也会带来性能开销,但正如我所知,这些线程一直保持活动状态,直到每次迭代都再次执行上述代码
  • omp\u set\u num\u threads
    设置为32(我在一台32核的机器上)
  • Ubuntu,gcc 7.4
干杯

IMHO

将每个元素复制两次:复制到threaded1/2中,然后复制到validobjs中。 它会使你的代码变慢


您可以使用同步将元素添加到单个向量中。

我不擅长多线程,但我会尝试一下:

这种操作适合多线程吗

我会说是的。特别是如果你有巨大的数据集,你可以进一步分割它们,并行运行任意数量的过滤操作。但这取决于要处理的数据量,线程创建和同步不是免费的

正如线程版本末尾的合并一样

多线程代码看起来合理吗

我认为让每个线程处理独立数据是正确的

我能做些什么来提高性能,使其比无线程的情况更快

我认为有几点可能会提高性能:

  • 向量需要经常调整大小,这很昂贵。您可以使用来提前保留内存,从而减少重新分配的次数(在最佳情况下为0)

  • 最后两个向量的合并也是如此,这是一个临界点,第一保留:

    validobjs.reserve(v1.size() + v2.size());
    
    然后合并

  • 将对象从一个向量复制到另一个向量可能很昂贵,这取决于您复制的对象的大小,以及是否有执行更多代码的自定义复制构造函数。考虑仅将有效元素或指针的索引存储到有效元素。

  • 您还可以尝试在生成的向量中并行替换元素。如果默认构造元素的成本较低,而复制成本较高,那么这可能很有用

  • 像现在一样在两个线程中过滤数据
  • 同步它们并分配一个包含多个元素的向量:

    validobjs.resize(v1.size() + v2.size());
    
  • 让每个线程在向量的独立部分插入元素。例如,线程1将向索引
    1
    写入
    x
    ,线程2向索引
    x+1
    写入
    validobjs.size()-1

    尽管我不确定这是完全合法还是不明确的行为


  • 您还可以考虑使用
    std::list
    (链表)。连接链表或删除元素是在固定的时间内进行的,但是添加元素要比使用保留内存的
    std::vector
    稍微慢一点



    这就是我的想法,我希望其中有一些有用的东西。

    我们可能需要更多的代码来继续。什么是
    v1
    v2
    ?您能否再发布一点代码,使多线程代码易于执行?如何测量时间?@MarkLoeser sure-Intel®Xeon(R)Gold 6130 CPU@2.10GHz×32 w/64gb RAM为什么有两个线程化变量1和2?您是否希望threaded1