Ошибка 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 ответа

Решение

Мне действительно интересно, если эта вещь компилируется? Вы указываете default(none), но последовательно используйте данные членов вашего класса. Они все статичны?

Что вы можете сделать, это либо я) уйти 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. Это может или не может дать некоторое преимущество в производительности, избегая последовательного доступа. У меня была похожая проблема несколько дней назад, и не было никакой разницы.

Вы не можете гарантировать порядок, в котором выполняются потоки, если вам нужно гарантировать, что вы делаете операторы if, как вы, или просто не распараллеливаете их, потому что это критический раздел.

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

Другие вопросы по тегам