Файл MEX выполняется последовательно, несмотря на параллельную компиляцию

Я тестирую базовый распараллеленный код openmp с mex-файлом. Проблема в том, что он, кажется, работает только с одним потоком, несмотря на мое указание запускать его с двумя потоками. Вот код:

#include "mex.h"
#include "omp.h"

#include <iostream>


void mexFunction(int nlhs, mxArray *plhs[],int nrhs,const mxArray *prhs[])
{
    using namespace std;
    #define x_out plhs[0]
    #define x_in prhs[0]

    double *x;
    double y;
    x_out=mxCreateDoubleMatrix(1,1,mxREAL);
    x=mxGetPr(x_out);
    y=mxGetScalar(x_in);

    x[0]=y;    
    omp_set_num_threads(2);
    int Nthreads=omp_get_num_threads();
    cout<<Nthreads<<"\n";
    #pragma omp parallel
    {
        int ithread=omp_get_thread_num();

        #pragma omp for
                for (int i=0;i<10;i++)
                    cout<<"Hello! " <<i<<"\n";
    }
    return;
}

Я использую следующую строку компиляции -

mex -v paralletestmex.cpp CC=g++ CFLAGS="\$CFLAGS -fopenmp" LDFLAGS="\$LDFLAGS -fopenmp"

и в подробном описании появляется флаг fopenmp, поэтому я предполагаю, что он компилирует его для параллельной работы.

Вывод, который я получаю, -

1
Hello! 0
Hello! 1
Hello! 2
Hello! 3
Hello! 4
Hello! 5
Hello! 6
Hello! 7
Hello! 8
Hello! 9

Показывает, что по какой-то причине создается только 1 поток. Это простой тест для проблемы, с которой я столкнулся в более сложном коде. Когда я запускаю это как обычный файл С++ без использования mex, тот же код работает нормально.

Любая помощь приветствуется. Благодарю вас! Сиддхарт


person Siddharth Krishnamoorthy    schedule 28.10.2013    source источник
comment
вы нигде не печатаете ithread. Также openmp может принять решение не распараллеливать ваш код, если итераций слишком мало (развернуть цикл) и если у вас есть только один процессор/ядро.   -  person Lachezar    schedule 29.10.2013
comment
Привет, на самом деле у меня изначально не было цикла for, и я просто печатал ithread, и это показало мне только 0. Кроме того, когда я не делаю этого в mex, openmp распараллеливает его. Я просто не делаю это для мекс по какой-то причине.   -  person Siddharth Krishnamoorthy    schedule 29.10.2013


Ответы (2)


Это чрезвычайно распространенная ошибка: omp_get_num_threads() возвращает количество потоков в текущей команде. При вызове за пределами региона parallel он всегда возвращает 1, поскольку по определению программы OpenMP выполняются только с одним потоком (главным потоком) за пределами параллельных регионов.

Дополнительным вызовом omp_set_num_threads() является omp_get_max_threads().

Также обратите внимание, что вызов omp_set_num_threads() является очень плохой практикой программирования, когда речь идет о написании модулей и библиотечных функций. Причина в том, что он фиксирует количество потоков для всех последующих параллельных регионов и, таким образом, может повлиять на другой код. Гораздо лучший способ сделать это — использовать предложение num_threads:

#pragma omp parallel num_threads(2)
{
   // ...
}
person Hristo Iliev    schedule 29.10.2013
comment
Спасибо за ваш ответ и комментарии. Поэтому я переместил части omp_get_num_threads() и cout‹‹Nthreads внутрь параллельной области и сделал #pragma omp parallel num_threads(2), но это все равно не меняет мой вывод. Он по-прежнему отображает N_threads как 1 и вывод в том же порядке. - person Siddharth Krishnamoorthy; 29.10.2013

Хорошо, я провел небольшое исследование, и оказалось, что CXXOPTIMFLAGS в файле mexopts.sh также необходимо изменить. Итак, в строку компиляции я добавил:

CXXOPTIMFLAGS="\$CXXOPTIMFLAGS -fopenmp" 

и это, кажется, делает работу.

Спасибо за вашу помощь!

person Siddharth Krishnamoorthy    schedule 29.10.2013