将并行程序从 openMP 转换为 openCL
Converting parallel program from openMP to openCL
我只是想知道如何将以下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 探查器我注意到大部分执行时间花在了 InsertCandidate() 函数上,我正在考虑编写一个内核来在 GPU 上执行这个函数。此函数最昂贵的操作是 for
指令。但是可以看出,每个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吗?
也许可以将您的示例代码转换为 opencl,但是我发现这样做有几个问题。
- 开始时似乎没有多少并行执行。更多的工人可能根本没有帮助。
- 在执行期间向进程添加工作是 opencl 中的一项相当新的功能。您将不得不使用 opencl 2.0,或者提前知道将添加多少工作,并预先分配内存来存储新的数据结构。对 InsertCandidate 的调用可能是 "can't" 转换为 opencl 的部分。
如果函数足够大,您可以改为将调用移植到 this->Prob(...)。您需要能够通过将参数存储在合适的数据结构中来缓存一堆调用。 'a bunch' 我的意思是至少有数百个,但最好是数千个或更多。同样,只有当 this->Prob() 对于所有调用都是恒定的,并且足够复杂以值得往返 opencl 设备并返回时,这才值得。
我只是想知道如何将以下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 探查器我注意到大部分执行时间花在了 InsertCandidate() 函数上,我正在考虑编写一个内核来在 GPU 上执行这个函数。此函数最昂贵的操作是 for
指令。但是可以看出,每个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吗?
也许可以将您的示例代码转换为 opencl,但是我发现这样做有几个问题。
- 开始时似乎没有多少并行执行。更多的工人可能根本没有帮助。
- 在执行期间向进程添加工作是 opencl 中的一项相当新的功能。您将不得不使用 opencl 2.0,或者提前知道将添加多少工作,并预先分配内存来存储新的数据结构。对 InsertCandidate 的调用可能是 "can't" 转换为 opencl 的部分。
如果函数足够大,您可以改为将调用移植到 this->Prob(...)。您需要能够通过将参数存储在合适的数据结构中来缓存一堆调用。 'a bunch' 我的意思是至少有数百个,但最好是数千个或更多。同样,只有当 this->Prob() 对于所有调用都是恒定的,并且足够复杂以值得往返 opencl 设备并返回时,这才值得。