C++ C++;带有private和shared子句的OpenMP计算错误
我有一个循环要与OpenMP并行,但有多个计算错误,可能是因为我不了解OpenMP的多线程概念:C++ C++;带有private和shared子句的OpenMP计算错误,c++,multithreading,openmp,C++,Multithreading,Openmp,我有一个循环要与OpenMP并行,但有多个计算错误,可能是因为我不了解OpenMP的多线程概念: for ( int i = -X/2; i < X/2; ++i ) { base.y = anchor + i*rho_step; temp = some_function( base ); if( temp > response ) { buffer.y = base.y; response = temp; }
for ( int i = -X/2; i < X/2; ++i )
{
base.y = anchor + i*rho_step;
temp = some_function( base );
if( temp > response )
{
buffer.y = base.y;
response = temp;
}
}
有什么问题吗?(
anchor
和rho_step
是这个循环中的常量)为了让代码处理缓冲区的跨线程变量和响应变量,您需要为它们使用一些每个线程的局部变量,并对它们执行最终的缩减以更新它们的共享对应项
以下是它的外观(未经测试):
#pragma omp parallel firstprivate(基本)
{
自动本地响应=响应;
自动本地缓冲区=缓冲区;
#pragma omp for
对于(int i=-X/2;i本地响应)
{
localBuffer.y=base.y;
localResponse=temp;
}
}
#pragma-omp-critical
{
if(localResponse>response)
{
buffer.y=localBuffer.y;
响应=本地响应;
}
}
}
不幸的是,这产生了同样的结果。如果buffer
和response
是共享的,并且处于关键部分,我不明白为什么我们需要每个线程的局部变量。对于每个不同的i
我们有不同的base.y
和temp
,我们只需管理每个线程有自己的base.y
-s和temp
-s,并检查它们是否必须逐个修改缓冲区和响应。(很抱歉我的知识不完善。)我只是做了一个更改,将base
firstprivate
放在这里,因为不清楚其他字段在上下文中是否重要。无论如何,我的方法的要点是,最终的归约(临界
部分)在并行循环之外,但在并行部分之内。它只在最后出现一次,而不是像在您的代码中那样在每次迭代中出现。firstprivate
解决了问题,现在您和我的版本都可以工作了,谢谢!尽管您的版本存在变量缓冲区
和响应
的争用条件,但要小心(这是制作本地版本和在关键
部分进行最终缩减的全部要点)。因此,尽管您的版本似乎与firstprivate
一起工作,但它本质上是错误的。在我看来,它似乎存在数据依赖关系:response
可能会更改,并直接影响以后的循环过程。如果是这样,您就无法使用任何多线程工具轻松地加速循环。只有当某些函数
需要大量时间时,才可以添加多线程。响应
仅在if条件为true时才会更改。some_函数做了很多事情,这就是为什么我试图节省运行时间。谢谢你的评论!
#pragma omp parallel for shared (buffer, response) private(base, temp)
for ( int i = -X/2; i < X/2; ++i )
{
base.y = anchor + i*rho_step;
temp = some_function( base );
if( temp > response )
{
buffer.y = base.y;
response = temp;
}
}
omp_lock_t writelock;
omp_init_lock(&writelock);
omp_set_num_threads (4);
#pragma omp parallel for
for ( int i = -X/2; i < X/2; ++i )
{
omp_set_lock(&writelock);
base.y = anchor + i*rho_step;
temp = some_function( base );
if( temp > response )
{
buffer.y = base.y;
response = temp;
}
omp_unset_lock(&writelock);
}
omp_destroy_lock(&writelock);
#pragma omp parallel firstprivate( base )
{
auto localResponse = response;
auto localBuffer = buffer;
#pragma omp for
for ( int i = -X/2; i < X/2; ++i )
{
base.y = anchor + i * rho_step;
auto temp = some_function( base );
if ( temp > localResponse )
{
localBuffer.y = base.y;
localResponse = temp;
}
}
#pragma omp critical
{
if ( localResponse > response )
{
buffer.y = localBuffer.y;
response = localResponse;
}
}
}