将并行程序从openMP转换为openCL

时间:2015-07-31 08:25:23

标签: c++ parallel-processing opencl openmp

我只是想知道如何将以下openMP程序转换为openCL程序。

使用openMP实现的算法的并行部分如下所示:

#pragma omp parallel
  {
    int thread_id = omp_get_thread_num();

    //double mt_probThreshold = mt_nProbThreshold_;
    double mt_probThreshold = nProbThreshold;

    int mt_nMaxCandidate = mt_nMaxCandidate_;
    double mt_nMinProb = mt_nMinProb_;

    int has_next = 1;
    std::list<ScrBox3d> mt_detected;
    ScrBox3d  sample;
    while(has_next) {
#pragma omp critical
    {  // '{' is very important and define the block of code that needs lock.
      // Don't remove this pair of '{' and '}'.
      if(piter_ == box_.end()) {
        has_next = 0;
      } else{
        sample = *piter_;
        ++piter_;
      }
    }  // '}' is very important and define the block of code that needs lock.

    if(has_next){
      this->SetSample(&sample, thread_id);
      //UpdateSample(sample, thread_id); // May be necesssary for more sophisticated features
      sample._prob = (float)this->Prob( true, thread_id, mt_probThreshold);
      //sample._prob = (float)_clf->LogLikelihood( thread_id);
      InsertCandidate( mt_detected, sample, mt_probThreshold, mt_nMaxCandidate, mt_nMinProb );
    }
  }

#pragma omp critical
  {  // '{' is very important and define the block of code that needs lock.
    // Don't remove this pair of '{' and '}'.
    if(mt_detected_.size()==0) {
      mt_detected_    = mt_detected;
      //mt_nProbThreshold_  = mt_probThreshold;
      nProbThreshold = mt_probThreshold;
    } else {
      for(std::list<ScrBox3d>::iterator it = mt_detected.begin(); 
          it!=mt_detected.end(); ++it)
        InsertCandidate( mt_detected_, *it, /*mt_nProbThreshold_*/nProbThreshold, 
        mt_nMaxCandidate_, mt_nMinProb_ );
      }
    }  // '}' is very important and define the block of code that needs lock.
  }//parallel section end

我的问题是:是否可以使用openCL实现此部分? 我按照了一系列openCL教程,我理解了工作方式,我在.cu文件中编写代码,(我以前安装过CUDA工具包),但在这种情况下情况比较复杂,因为有很多使用了头文件,模板类和面向对象编程。

如何将openMP中实现的此部分转换为openCL? 我应该创建一个新的.cu文件吗?

任何建议都有帮助。 提前谢谢。

编辑:

使用VS profiler我发现在InsertCandidate()函数上花费的执行时间最多,我正在考虑编写一个内核来在GPU上执行这个函数。该函数最昂贵的操作是for指令。但是可以看出,每个循环包含3个if指令,这可能导致分歧,导致序列化,即使在GPU上执行也是如此。

for( iter = detected.begin(); iter != detected.end(); iter++ )
    {
        if( nCandidate == nMaxCandidate-1 )
            nProbThreshold = iter->_prob;

        if( box._prob >= iter->_prob )
            break;
        if( nCandidate >= nMaxCandidate && box._prob <= nMinProb )
            break;
        nCandidate ++;
    }

作为结论,该程序可以转换为openCL吗?

1 个答案:

答案 0 :(得分:2)

有可能将您的示例代码转换为opencl,但是我发现了这样做的几个问题。

  1. 开始时似乎没有太多的并行执行。更多工人可能根本没有帮助。
  2. 在执行期间添加工作进程是opencl中最近的一项功能。您必须使用opencl 2.0,或者事先知道将添加多少工作,并预先分配内存以存储新的数据结构。对InsertCandidate的调用可能是“无法”转换为opencl的部分。
  3. 如果功能足够大,您可以将呼叫移植到此 - &gt; Prob(...)。通过将参数存储在合适的数据结构中,您需要能够缓存一堆调用。 “一堆”我的意思是至少数百,但理想情况下数千或更多。同样,只有当这个&gt; Prob()对于所有调用都是常量时,这是值得的,并且复杂到足以值得往返于opencl设备并返回。