Параллельные вызовы функций OpenMP - PullRequest
1 голос
/ 03 июля 2019

У меня есть некоторый код на Фортране, который был написан для научных целей.Существует два вызова условных функций, которые проверяются и выполняются последовательно.Вызовы этих функций я бы хотел распараллелить, так как они не связаны друг с другом.Тем не менее, я не уверен, как лучше это сделать.

Пример кода, который у меня есть, выглядит следующим образом:

...

if ( flag1 ) then
  stat1 = func1( tm, dt, struct % a, struct % b )
  if ( stat1 .gt. 0 ) then
    call die_error("error message")
    status = 1
    return
  end if
end if

if ( flag2 ) then
  stat2 = func2( tm, dt, struct % a, struct % c )
  if ( stat2 .gt. 0 ) then
    call die_error("error message 2")
    status = 1
    return
  end if
end if

...

Флаги flag1 и flag2 являются пользовательскимиопределено, один из них может быть правдой или оба могут быть правдой, или оба могут быть ложными, поэтому они проверяются независимо.

Аргументы функции tm и dt являются переменными целочисленной и двойной точности соответственно, но они не изменяются func1 или func2.

Настраиваемый тип данных structсодержит три массива двойной точности: a, b и c.Массив struct % a не изменяется func1 или func2.Однако struct % b - это , измененное func1, а struct % c - , измененное func2.

В конкретном случае, когда flag1 и flag2 оба истинны, тогда func1 и func2 могут быть вызваны параллельно.Однако я не уверен в следующем:

  1. как правильно обращаться с пользовательским типом данных;например, нужны ли мне блокировки?
  2. как правильно обращаться с struct % a, так как он не изменяется кодом;firstprivate(struct % a) например?
  3. как правильно реализовать условия, поскольку я хочу только распараллелить, если flag1 и flag2 оба истинны?

Моя попытка заключается в следующем:

...

!$omp parallel num_threads(2) firstprivate(tm, dt, struct % a) if(flag1 .and. flag2)
  !$omp master
    !$omp task lastprivate(stat1)
      stat1 = func1( tm, dt, struct % a, struct % b )
    !$omp end task

    !$omp task lastprivate(stat2)
      stat2 = func2( tm, dt, struct % a, struct % c )
    !$omp end task

    !$omp taskwait

    if ( (stat1 .gt. 0) .or. (stat2 .gt. 0) ) then
      call die_error("error message")
      status = 1
      return
    end if
  !$omp end master
!$omp end parallel

if ( flag1 .and. .not.flag2 ) then
  stat1 = func1( tm, dt, struct % a, struct % b )
  if ( stat1 .gt. 0 ) then
    call die_error("error message")
    status = 1
    return
  end if
end if

if ( flag2 .and. .not.flag1 ) then
  stat2 = func2( tm, dt, struct % a, struct % c )
  if ( stat2 .gt. 0 ) then
    call die_error("error message 2")
    status = 1
    return
  end if
end if

...

Несколько вопросов, которые у меня есть выше:

Нужна ли директива !$omp master? Следует ли использовать директиву !$omp sections вместо !$omp task? Безопасен ли мой возврат из директивы !$omp parallel, если либо func1 или func2 не удалось?
...