Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.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++ OpenCV中聚类方法的并行化_C++_Multithreading_Opencv_Parallel Processing - Fatal编程技术网

C++ OpenCV中聚类方法的并行化

C++ OpenCV中聚类方法的并行化,c++,multithreading,opencv,parallel-processing,C++,Multithreading,Opencv,Parallel Processing,在我的项目中,我正在训练一个循环闭合检测的fabMap算法。培训包括创建描述符、词汇和Chow Liu tree。我有一个超过10000张图片的数据库。我正在使用一个非常好的桌面(12核双线程、32GB内存和6GB Nvidia图形卡),我希望在培训我的系统时充分利用它。我在Windows7,64位系统上使用opencv 3.0,启用TBB 问题是,只有描述符的提取是多线程的。Chow Liu树的聚类和构建在单个线程中执行。BOWMSCTrainer类的cluster()方法有3个嵌套的for(

在我的项目中,我正在训练一个循环闭合检测的fabMap算法。培训包括创建描述符、词汇和Chow Liu tree。我有一个超过10000张图片的数据库。我正在使用一个非常好的桌面(12核双线程、32GB内存和6GB Nvidia图形卡),我希望在培训我的系统时充分利用它。我在Windows7,64位系统上使用opencv 3.0,启用TBB

问题是,只有描述符的提取是多线程的。Chow Liu树的聚类和构建在单个线程中执行。BOWMSCTrainer类的cluster()方法有3个嵌套的
for()
循环,每个循环都依赖于前一个循环,甚至可以动态指定嵌套循环的大小。这是cluster()方法的核心:

/\u描述符是一个矩阵,其中每一行都是一个描述符
Mat icovar=Mat::eye(_descriptors.cols,_descriptors.cols,_descriptors.type());
性病:病媒中心;
初始化中心。向后推(_描述符。第(0)行);
对于(int i=1;i<_descriptors.rows;i++){
双重思维者=DBL_MAX;
对于(size_t j=0;jclusterSize)
初始化中心。推回(_描述符。第(i)行);
}
std::向量簇;
clusters.resize(initialCentres.size());
对于(int i=0;i<_descriptors.rows;i++){
int指数=0;双距离=0,minDist=DBL_MAX;
对于(size_t j=0;j
为了了解培训需要多长时间,我对数据库进行了抽样。我从10张图片(约20000个描述符)开始,花了大约40分钟。对于100幅图像(约300000个描述符)的样本,整个过程大约需要60个小时,而对于1000幅图像(将呈现一个不错的词汇表),我担心可能需要8个月(!)(如果方法是O(n²)->60小时*10²~8个月),我不想想象整个数据库需要多长时间

所以,我的问题是:有没有可能以某种方式并行执行cluster()方法,这样系统的训练就不会花费太多的时间?我曾想过应用openMP pragmas,或为每个循环创建一个线程,但考虑到
for()
循环的动态性,我认为这是不可能的。虽然我熟悉并行编程和多线程,但我在这个领域根本不是专家


非常感谢

出于价值考虑,我将我提出的代码留在这里,使用OpenCV的调用
parallel\u。我还在代码中添加了一个特性,现在它删除了所有小于阈值的集群。该代码有效地加快了流程:

//The first nest of fors remains untouched, but the following ones: 

std::vector<std::list<cv::Mat> > clusters;
clusters.resize(initialCentres.size());

Mutex lock = Mutex();
parallel_for_(cv::Range(0, _descriptors.rows - 1),
        for_createClusters(clusters, initialCentres, icovar, _descriptors, lock));

Mat vocabulary;
Mat centre = Mat::zeros(1,_descriptors.cols,_descriptors.type());
parallel_for_(cv::Range(0, clusters.size() - 1), for_estimateCentres(clusters,
        vocabulary, centre, minSize, lock));
//fors的第一个嵌套保持不变,但以下嵌套:
std::向量簇;
clusters.resize(initialCentres.size());
互斥锁=互斥锁();
并行_表示(cv::Range(0,_descriptor.rows-1),
对于_createClusters(集群、初始中心、icovar、_描述符、锁));
词汇表;
Mat center=Mat::zeros(1,_descriptors.cols,_descriptors.type());
并行_用于_(cv::Range(0,clusters.size()-1),用于_估计中心(clusters,
词汇表、中心词、最小值、锁定词);
在标题中:

//parallel_for_ for creating clusters:
class CV_EXPORTS for_createClusters: public ParallelLoopBody {
private:

std::vector<std::list<cv::Mat> >& bufferCluster;
const std::vector<Mat> initCentres;
const Mat icovar;
const Mat descriptorsParallel;
Mutex& lock_for;

public:
for_createClusters(std::vector<std::list<cv::Mat> >& _buffCl,
        const std::vector<Mat> _initCentres, const Mat _icovar,
        const Mat _descriptors, Mutex& _lock_for)
: bufferCluster (_buffCl), initCentres(_initCentres), icovar(_icovar),
  descriptorsParallel(_descriptors), lock_for(_lock_for){}


virtual void operator()( const cv::Range &r ) const
{
    for (register int f = r.start; f != r.end; ++f)
    {
        int index = 0; double dist = 0, minDist = DBL_MAX;
        for (register size_t j = 0; j < initCentres.size(); j++) {
            dist = cv::Mahalanobis(descriptorsParallel.row(f),
                    initCentres[j],icovar);
            if (dist < minDist) {
                minDist = dist;
                index = (int)j;
            }
        }
        {
//              AutoLock Lock(lock_for);
            lock_for.lock();
            bufferCluster[index].push_back(descriptorsParallel.row(f));
            lock_for.unlock();
        }
    }
    }
};

class CV_EXPORTS for_estimateCentres: public ParallelLoopBody {
private:

const std::vector<std::list<cv::Mat> > bufferCluster;
Mat& vocabulary;
const Mat centre;
const int minSizCl;
Mutex& lock_for;

public:
for_estimateCentres(const std::vector<std::list<cv::Mat> > _bufferCluster,
        Mat& _vocabulary, const Mat _centre, const int _minSizCl, Mutex& _lock_for)
: bufferCluster(_bufferCluster), vocabulary(_vocabulary),
  centre(_centre), minSizCl(_minSizCl), lock_for(_lock_for){}

virtual void operator()( const cv::Range &r ) const
{
    Mat ctr = Mat::zeros(1, centre.cols,centre.type());

    for (register int f = r.start; f != r.end; ++f){
        ctr.setTo(0);
        //Not taking into account small clusters
        if(bufferCluster[f].size() >= (size_t) minSizCl)
        {
            for (register std::list<cv::Mat>::const_iterator
                    Ci = bufferCluster[f].begin();
                    Ci != bufferCluster[f].end(); Ci++)
                        ctr += *Ci;

            ctr /= (double)bufferCluster[f].size();

            {
//              AutoLock Lock(lock_for);
                lock_for.lock();
                vocabulary.push_back(ctr);
                lock_for.unlock();
            }
        }
    }
  }
};
//用于创建群集的并行\u:
类CV_导出用于_createClusters:public ParallelLoopBody{
私人:
std::向量和缓冲聚类;
常数std::向量初始化中心;
const-Mat-icovar;
常数矩阵描述符并行;
互斥和锁定;
公众:
对于_createClusters(std::vector和_buffCl,
常数std::向量_initcenters,常数Mat _icovar,
常数矩阵描述符、互斥锁和锁(用于)
:bufferCluster(_buffCl)、initcenters(_initcenters)、icovar(_icovar),
描述符并行(_描述符),锁定(_锁定){
虚拟void运算符()(常量cv::Range&r)常量
{
用于(寄存器int f=r.start;f!=r.end;++f)
{
int指数=0;双距离=0,minDist=DBL_MAX;
用于(寄存器大小j=0;j//parallel_for_ for creating clusters:
class CV_EXPORTS for_createClusters: public ParallelLoopBody {
private:

std::vector<std::list<cv::Mat> >& bufferCluster;
const std::vector<Mat> initCentres;
const Mat icovar;
const Mat descriptorsParallel;
Mutex& lock_for;

public:
for_createClusters(std::vector<std::list<cv::Mat> >& _buffCl,
        const std::vector<Mat> _initCentres, const Mat _icovar,
        const Mat _descriptors, Mutex& _lock_for)
: bufferCluster (_buffCl), initCentres(_initCentres), icovar(_icovar),
  descriptorsParallel(_descriptors), lock_for(_lock_for){}


virtual void operator()( const cv::Range &r ) const
{
    for (register int f = r.start; f != r.end; ++f)
    {
        int index = 0; double dist = 0, minDist = DBL_MAX;
        for (register size_t j = 0; j < initCentres.size(); j++) {
            dist = cv::Mahalanobis(descriptorsParallel.row(f),
                    initCentres[j],icovar);
            if (dist < minDist) {
                minDist = dist;
                index = (int)j;
            }
        }
        {
//              AutoLock Lock(lock_for);
            lock_for.lock();
            bufferCluster[index].push_back(descriptorsParallel.row(f));
            lock_for.unlock();
        }
    }
    }
};

class CV_EXPORTS for_estimateCentres: public ParallelLoopBody {
private:

const std::vector<std::list<cv::Mat> > bufferCluster;
Mat& vocabulary;
const Mat centre;
const int minSizCl;
Mutex& lock_for;

public:
for_estimateCentres(const std::vector<std::list<cv::Mat> > _bufferCluster,
        Mat& _vocabulary, const Mat _centre, const int _minSizCl, Mutex& _lock_for)
: bufferCluster(_bufferCluster), vocabulary(_vocabulary),
  centre(_centre), minSizCl(_minSizCl), lock_for(_lock_for){}

virtual void operator()( const cv::Range &r ) const
{
    Mat ctr = Mat::zeros(1, centre.cols,centre.type());

    for (register int f = r.start; f != r.end; ++f){
        ctr.setTo(0);
        //Not taking into account small clusters
        if(bufferCluster[f].size() >= (size_t) minSizCl)
        {
            for (register std::list<cv::Mat>::const_iterator
                    Ci = bufferCluster[f].begin();
                    Ci != bufferCluster[f].end(); Ci++)
                        ctr += *Ci;

            ctr /= (double)bufferCluster[f].size();

            {
//              AutoLock Lock(lock_for);
                lock_for.lock();
                vocabulary.push_back(ctr);
                lock_for.unlock();
            }
        }
    }
  }
};