私有和共享子句的C ++ OpenMP计算错误

时间:2017-08-22 11:10:09

标签: c++ multithreading openmp

我有一个for循环要与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;
    }
}

这很好用,然后我做了以下更改:

#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;
    }
}

在此代码中,buffer.yresponse都不会包含正确的值。根据我的理解,每个线程都应该拥有base.ytemp的自己副本,它们只是计算的临时变量,并且必须共享bufferresponse(他们将存储计算数据),但这并不像我预期的那样有效。

唯一完美的版本如下,但显然没有性能提升:

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);

可能是什么问题? (anchorrho_step是此循环中的常量)

1 个答案:

答案 0 :(得分:2)

为了让您的代码处理bufferresponse变量的跨线程,您需要为它们使用一些每线程局部变量,并执行最终减少他们更新他们共享的同行。

以下是它的样子(未经测试):

#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;
        }
    }
}