openmp bug与径向计算

时间:2014-03-24 22:37:29

标签: c++ multithreading algorithm parallel-processing openmp

#pragma omp parallel for schedule(static) default(none)
for(int row = 0; row < m_height; row++)
{
    for(int col = 0; col < m_width; col++)
    {
       int RySqr, RxSqr;

       SettingSigmaN(eta, m_RxInitial + col, m_RyInitial + row , RxSqr, RySqr);

       FunctionUsing(RySqr,RxSqr); 
    }
} 

void CImagePro::SettingSigmaN(int Eta, int x, int y, int &RxSqr, int &RySqr, int &returnValue)
{
    int rSqr = GetRadius(x,y,RxSqr,RySqr);
    returnValue = GetNumberFromTable(rsqr);
}


int CImagePro::GetRadius(int x, int y, int &RxSqr, int &RySqr) 
{   
    if (x == m_RxInitial)
    {       
        RxSqr = m_RxSqrInitial;
        if (y == m_RyInitial) 
        {
            RySqr = m_RySqrInitial;
        }
        else if ( abs(y) % 2 == abs(m_RyInitial) % 2)
        {
            RySqr = RySqr + (y<<2) + 4; //(y+2)^2
        }
    } 
    else 
    {
        RxSqr = RxSqr + ( x << 1) + 1; //(x+1)^2
    }   
    return clamp(((RxSqr+RySqr)>>RAD_RES_REDUCTION),0,(1<<(RAD_RES-RAD_RES_REDUCTION))-1);
}

好,所以这是我的代码,我的问题在GetRadius函数内。 因为我有很多线程,每个线程都在x,y的不同位置开始。但是我真的不明白GetRadius()里面的错误在哪里。

我想也许是RySqr计算。你能建议一种调试方法吗?或者你能看出我的问题吗?

更新:

这修复了我的大部分代码: 我还是不太懂,为什么不同线程之间会有跳跃。

  int CImagePro::GetRadius(int x, int y, int &RxSqr, int &RySqr) 
  { 
     if (x == m_RxInitial)
     {      
        RxSqr = m_RxSqrInitial;
     }
     else
     {
         RxSqr = x * x;
     }

    if (y == m_RyInitial)
    {
        RySqr = m_RySqrInitial;
    }
    else if (abs(y) % 2 == abs(m_RyInitial) % 2)
    {
        RySqr = y * y;
    }
    return clamp(( (RxSqr + RySqr) >> RAD_RES_REDUCTION), 0, ( 1 << (RAD_RES - RAD_RES_REDUCTION) ) - 1);   
}

2 个答案:

答案 0 :(得分:1)

我真的很想知道这件事是否汇编了?您指定default(none),但始终使用您班级的数据成员。它们都是静态的吗?

你可以做的是i)离开default(none),这意味着default(shared),ii)通过明确地共享它们来共享访问值,或者iii)初始化你在里面使用的变量并行区域,以便每个线程拥有它自己的私有副本,比如m_RxInitial,称为p_RxInitial等。第一个选项几乎可以保证让您陷入麻烦。

以下说明选项ii):

1)制作一个包含你需要传递的所有东西的助手类,对你来说可能是

struct ShareData{
    int s_RxInitial
    /* ... */
}

2)在包含并行部分的成员函数中,在并行循环定义

之前
ShareData SD;
SD.s_RxInitial = m_RxInitial;
/* ... */

3)将其交给平行部分

#pragma omp parallel for schedule(static), default(none), shared(SD)

4)在函数调用中使用SD数据库。

我希望这很清楚。如果有人提供更优雅的解决方案,我将不胜感激。

如果您想要选项iii)的私有变量,则可以说firstprivate(SD)而不是shared(SD)。这将使每个线程初始化(到原始值)SD的私有副本。通过避免串行访问,它可能会或可能不会提供一些性能优势。几天前我遇到了类似的问题,并没有什么区别。

答案 1 :(得分:-2)

如果你需要保证像你一样制作if语句,或者根本不进行并行化,因为它是一个关键部分,你不能保证线程执行的顺序。

http://bisqwit.iki.fi/story/howto/openmp/