Ошибка сегментации с задачами OpenMP в подпрограммах (Intel Fortran 2018, обновление 1) - PullRequest
0 голосов
/ 25 апреля 2018

Я столкнулся со следующей проблемой при использовании компилятора Intel Fortran 2018 Update 1. Я реализовал блочный алгоритм для вычисления неуместного треугольно-матричного произведения C := alpha * A * B + beta *C, где A - верхняя треугольная матрица. Поскольку продукт матричной матрицы имеет большой потенциал для распараллеливания, я сделал это, используя задачи OpenMP и зависимости задач. Завершаем со следующим кодом:

SUBROUTINE DTRMM3(M,N,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
USE OMP_LIB
IMPLICIT NONE
DOUBLE PRECISION ALPHA,BETA
INTEGER LDA,LDB,LDC,M,N
DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*)
EXTERNAL DGEMM, DTRMM
INTRINSIC MAX
INTEGER K,KB,L,LB,J,JB
!     .. Parameters ..
DOUBLE PRECISION DONE,DZERO
PARAMETER (DONE=1.0D+0,DZERO=0.0D+0)
INTEGER NB
PARAMETER(NB=256)
!     .. Local Work...
DOUBLE PRECISION TMP(NB,NB)

IF (M.EQ.0 .OR. N.EQ.0) RETURN

IF (ALPHA.EQ.DZERO) THEN
    DO J = 1,N
        !$omp simd safelen(64)
        DO K = 1,M
            C(K,J) = BETA * C(K,J)
        END DO
        !$omp end simd
    END DO
    RETURN
END IF

DO L = 1,N,NB
    LB = MIN(NB,N - L + 1)
    DO K = 1,M,NB
        KB = MIN(NB, M - K + 1)
        !$omp task firstprivate(K,KB,L,LB) depend(inout: C(K:K+KB-1,L:L+LB-1)) shared(C,BETA)
        C(K:K+KB-1, L:L+LB-1) = BETA * C(K:K+KB-1,L:L+LB-1)
        !$omp end task
        DO J = K, M, NB
            JB = MIN(NB, M - J + 1)
            !$omp task firstprivate(K,KB,L,LB, J, JB) private(TMP) &
            !$omp& depend(in:A(K:K+KB-1,J:J+JB-1), B(J:J+JB+1,L:L+LB-1)) depend(inout: C(K:K+KB-1,L:L+LB-1)) &
            !$omp& shared(ALPHA,A,B,C,LDA,LDB,LDC) default(none)
            IF ( K .EQ. J ) THEN
                TMP(1:KB,1:LB) = B(K:K+KB-1,L:L+LB-1)
                CALL DTRMM("L","U","N","U", KB, LB, ALPHA, A(K,K), LDA, TMP, NB)
                C(K:K+KB-1, L:L+LB-1) = C(K:K+KB-1,L:L+LB-1) + TMP(1:KB,1:LB)
            ELSE
                CALL DGEMM("N", "N", KB, LB, JB, ALPHA, A(K,J), LDA, B(J,L), LDB, DONE, C(K,L),LDC)
            END IF
            !$omp end task
        END DO

    END DO
END DO
RETURN
END SUBROUTINE

и выполните его, используя:

!$omp parallel
!$omp master
CALL DTRMM3(M, N, ALPHA, A, LDA, B, LDB, BETA, C2, LDC)
!$omp end master
!$omp taskwait
!$omp end parallel

Весь пример можно найти здесь

Я скомпилировал код, используя исходный вид

ifort -xHost -O3 dtrmm3_test.f90  -qopenmp -mkl -g

и выполнение его на 16-ядерном Xeon Silver 4110 приводит к ошибке сегментации:

./a.out
512   786     0.00000000D+00   0.00000000D+00   0.00000000D+00  T
512   786     0.00000000D+00   0.10000000D+01   0.00000000D+00  T
512   786     0.00000000D+00   0.20000000D+01   0.00000000D+00  T
forrtl: severe (174): SIGSEGV, segmentation fault occurred
forrtl: severe (174): SIGSEGV, segmentation fault occurred
forrtl: severe (174): SIGSEGV, segmentation fault occurred

Первые три строки показывают, что путь ALPHA = 0.0 работает и падает только при вызове части алгоритма, основанной на задачах.

Uisng GCC 7.3 и Netlib BLAS все отлично работает без ошибок.

ОС: CentOS 7.4, Intel Fortran 2018, обновление 1, MKL 2018, обновление 1

1 Ответ

0 голосов
/ 30 апреля 2018

Мы смотрим на это (команда разработчиков компилятора и OMP в Intel) и скоро свяжемся с вами.

Между тем, обратите внимание, что в ваших внутренних задачах цикла я думаю, что вы хотите добавить «C» в свой общий список, поскольку у вас есть «default (none)» там.Компилятор должен был предупредить вас об этом (я заметил, что компилятор C ++ делает это, а Fortran этого не делает, так что это ошибка).

Исправленный ответ: наша команда компиляторов говорит, что при использовании общих предложений произошла ошибкавнутри подпрограммы - вы получаете общий доступ к C в подпрограмме, но не к C2 в main.

Для справки, это примечание к спецификации OpenMP в TR6: «Примечание. Передача разделяемой переменной в процедуру может привести к использованию временного хранилища вместо фактического аргумента, когда соответствующий фиктивный аргумент не имеет значения VALUE.Атрибут и его атрибут совместного использования данных определяются реализацией в соответствии с правилами в Разделе 2.20.1.2 на стр. 243. Эти условия эффективно приводят к ссылкам и определениям временного хранилища во время ссылки на процедуру. Кроме того, значениепеременная общего доступа копируется во промежуточное временное хранилище перед ссылкой на процедуру, если фиктивный аргумент не имеет атрибута INTENT (OUT), и возвращается из временного хранилища в разделяемую переменную, если фиктивный аргумент не имеет INTENT (IN)Атрибут. Любые ссылки на (или определения) общего хранилища, связанного с фиктивным аргументом любой другой задачей, должны быть синхронизированы со ссылкой на процедуру, чтобы избежать возможностиУсловия гонки. "

Попробуйте: Переместите ожидание задачи в конец подпрограммы DTRMM3, прямо перед возвратом.Когда будет достигнуто ожидание этой задачи, C все еще будет находиться в области видимости.

Спасибо!

Терри

...