Как исправить [ошибку сегментации] при распараллеливании цикла for с OpenMP? - PullRequest
0 голосов
/ 15 мая 2018

Я получаю ошибку сегментации при попытке распараллелить for -циклоп, и я не могу понять, почему.

Вот код:

#pragma omp parallel for schedule(static) reduction(+:ptx,pty)
    for(int i=0;i<numSteps;i++)
    {
        float energy=0;
        for(int idx=0;idx<patternNum;idx++)
        {
            float hitColor = getInterpolatedElement31(frame->dI,
                                        (float)(ptx+rotatetPattern[idx][0]),
                                        (float)(pty+rotatetPattern[idx][1]),
                                        wG[0]);

            if(!std::isfinite(hitColor)) {energy+=1e5; continue;}

            float residual = hitColor - (float)(hostToFrame_affine[0] * color[idx] + hostToFrame_affine[1]);
            float hw = fabs(residual) < setting_huberTH ? 1 : setting_huberTH / fabs(residual);
            energy += hw *residual*residual*(2-hw);
        }

        if(debugPrint)
            printf("step %.1f %.1f (id %f): energy = %f!\n",
                    ptx, pty, 0.0f, energy);

        errors[i] = energy;
        if(energy < bestEnergy)
        {
            bestU = ptx; bestV = pty; bestEnergy = energy; bestIdx = i;
        }

        ptx+=dx;
        pty+=dy;
    }
std::cout << "hello\n";

Функция, в которой находится этот for -петль, вызывается много раз, и ошибка сегментации вызывается только после многих итераций этой функции.

Вот почему я поставил cout << "hello", чтобы увидеть, сколько раз напечатан "hello".

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

Можете ли вы увидеть в этом цикле что-нибудь, что могло бы генерировать эту ошибку, используя эту прагму?

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Во-первых, я считаю, что сокращение (+: ptx, pty) - это не то, что вам нужно. Последовательный код предполагает, что ptx и pty увеличиваются для каждой следующей итерации, потому что их значения используются в вызове getInterpolatedElement31. Но с уменьшением у вас будет одинаковое значение на каждой итерации = начальное значение ptx (pty).

Во-вторых, общие переменные bestU , bestV , bestEnergy , bestIdx могут обновляться несколькими потоками одновременно

bestU = ptx; bestV = pty; bestEnergy = energy; bestIdx = i;

Итак, вам нужна некоторая синхронизация здесь.

0 голосов
/ 15 мая 2018

в выводе я вижу, что результаты , прежде чем я получу ошибку сегментации, не являются тем, чем предполагалось.

Хорошо, было бы справедливо рассмотреть проблему с корректно работающим кодом по содержанию.Тем не менее, позвольте мне набросать несколько советов о том, где могут возникнуть основные проблемы или как использовать стратегию каменного века для определения первопричины ...

Обычная практика - иметь данныеустановить с помощью известного решения, чтобы заблаговременно обнаружить ошибку / подтвердить достоверность схемы процесса на полученных результатах, просто повторно запустив известный набор тестов.


получаю ошибку сегментации ... и я не могу понять почему .

Общие подозрения:
декларация / адресация, связанные с:
idx == patternNum - 1: rotatetPattern[idx][ {0|1} ]
idx == patternNum - 1: color[idx]
i == numStep: errors[i]
? hostToFrame_affine[]
? wG[]

вызывающая подпись (и) и / или реализациядетали, как видно из:
float getInterpolatedElement31(...){ ... }
float fabs( ... ){ ... }


Самый простой следующий шаг?Сначала следите за следами пистолета для курения ... всегда ...

Самый простой шаг, доступный сейчас, - это добавление строки трейлинг-стопа DEBUG после каждой выполненной строки:

FLINTSTONEs_DEBUG_LOG( 0 ); // ------------------------------------------------

#pragma omp parallel for schedule(static) reduction(+:ptx,pty)
    for( int i =  0;
             i <  numSteps;
             i++
             )
    {   
        FLINTSTONEs_DEBUG_LOG( 1 ); // ----------------------------------------

        float energy = 0;

        FLINTSTONEs_DEBUG_LOG( 2 ); // ----------------------------------------

        for ( int idx =  0;
                  idx <  patternNum;
                  idx++
                  )
        {   FLINTSTONEs_DEBUG_LOG( 3 ); // ------------------------------------

            float hitColor = getInterpolatedElement31(
                                         frame->dI,
                                 (float)( ptx
                                        + rotatetPattern[idx][0]
                                          ),
                                 (float)( pty
                                        + rotatetPattern[idx][1]
                                          ),
                                        wG[0]
                                 );

            FLINTSTONEs_DEBUG_LOG( 4 ); // -----------------------------------

            if ( !std::isfinite( hitColor ) )
            {    
                  FLINTSTONEs_DEBUG_LOG( 5 ); // -----------------------------

                  energy += 1e5;

                  FLINTSTONEs_DEBUG_LOG( 6 ); // -----------------------------

                  continue;

                  FLINTSTONEs_DEBUG_LOG( 7 ); // -------------------------- ;)
            }

            float residual = hitColor
                           - (float) ( hostToFrame_affine[0]
                                     * color[idx]
                                     + hostToFrame_affine[1]
                                       );

            FLINTSTONEs_DEBUG_LOG( 8 ); // -----------------------------------

            float hw = setting_huberTH > fabs( residual )
                     ? 1
                     : setting_huberTH / fabs( residual );

            FLINTSTONEs_DEBUG_LOG( 9 ); // -----------------------------------

            energy += hw
                    * residual
                    * residual
                    * ( 2 - hw );

            FLINTSTONEs_DEBUG_LOG( 10 ); // ----------------------------------

        }

        FLINTSTONEs_DEBUG_LOG( 11 ); // --------------------------------------
        ...
        ..
        .

Использование:

        void FLINTSTONEs_DEBUG_LOG( int TracePOINT )
        {    printf( "ACK: thread[%d]'s smoke-trail has reached TracePOINT( %d )\n",
                     omp_get_thread_num(),
                     TracePOINT
                     );
        }

Конечно, это не наука о ракетостроении, но может легко показать вам след дыма после того, как в печати появилось следующее SegFault, так что, думаю, стоит упомянуть об этом и здесь.

Ябба Дабба Ду, иди, беги твердо, шаг за шагом.

...