OpenMP OpenBLAS вложенный параллелизм - PullRequest
0 голосов
/ 09 марта 2019

мы пытаемся запустить два экземпляра cblas_dgemm параллельно. Если общее количество потоков равно 16, мы бы хотели, чтобы каждый экземпляр работал с использованием 8 потоков. В настоящее время мы используем такую ​​структуру:

#pragma omp parallel num_threads(2)
{
   if (omp_get_thread_num() == 0){
     cblas_dgemm(...);
   }else {
     cblas_dgemm(...);
   }
}

Вот вопрос:

На верхнем уровне есть два потока OpenMP, каждый из которых активен внутри одного из блоков if / else. Теперь мы ожидаем, что эти потоки будут вызывать функции cblas_dgemm параллельно, а внутри этих функций cblas_dgemm мы ожидаем появления новых потоков.

Чтобы установить количество потоков, внутренних для каждого cblas_dgemm, мы устанавливаем соответствующую переменную окружения: setenv OPENBLAS_NUM_THREADS 8 Тем не менее, это не похоже на работу. Если мы измеряем время выполнения для каждого из параллельных вызовов, значения времени выполнения равны, но они равны времени выполнения отдельного вызова cblas_dgemm, когда вложенный параллелизм не используется и переменная среды OPENBLAS_NUM_THREADS установлена ​​в 1.

Что не так? и как мы можем иметь желаемое поведение? Есть ли способ узнать количество потоков внутри функции cblas_dgemm?

Большое спасибо за ваше время и помощь

1 Ответ

0 голосов
/ 11 марта 2019

Механизм, который вы пытаетесь использовать, называется «вложением», то есть создание новой параллельной области во внешней существующей параллельной области уже активно. Хотя большинство реализаций поддерживают вложение, по умолчанию оно отключено. Попробуйте установить OMP_NESTED=true в командной строке или вызвать omp_set_nested(true) перед первой директивой OpenMP в вашем коде.

Я бы также изменил приведенный выше код следующим образом:

#pragma omp parallel num_threads(2)
{
#pragma omp sections
#pragma omp section
    {
        cblas_dgemm(...);
    }
#pragma omp section
    {
        cblas_dgemm(...);
    }
}

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

...