OpenACC: как применить предложение сокращения к структурной переменной

Мне просто нужно применить предложение reduction(max: ) к Dts->t, но ничего не работает, я пробовал reduction(max:Dts.t), reduction(max:Dts->t), reduction(max:Dts) и reduction(max:t).

  #pragma acc parallel loop collapse(3) reduction(max:t) present(Dts) 
        for (k = KBEG; k <= KEND; k++){
        for (j = JBEG; j <= JEND; j++){
        for (i = IBEG; i <= IEND; i++){
          Dts->t = MAX(Dts->t, C_dt[k][j][i]);
         
        }}}

Я получаю такие типы ошибок:

PGC-S-0035-Syntax error: Recovery attempted by replacing '.' by ',' (update_stage.c: 450)
PGC-S-0035-Syntax error: Recovery attempted by replacing identifier present by accparallel (update_stage.c: 450)
PGC-S-0040-Illegal use of symbol, invDt_hyp (update_stage.c: 450)
PGC-S-0036-Syntax error: Recovery attempted by inserting <nl> before keyword for (update_stage.c: 451)
PGC-S-0978-The clause parallel is deprecated; use clause gang instead (update_stage.c: 451)
PGC-S-0374-Clause gang(value) not allowed in #pragma acc parallel loop (update_stage.c: 451)

Dts — это переменная типа Step.

typedef struct Step_{
  double *cmax; 
  double t;  
  .
  .
  .
} Step;

Цикл, который я пытаюсь ускорить, находится в подпрограмме, вызываемой в основной функции. В основной функции определяется Dts и там я пишу

#pragma acc enter data create(Dts)

#pragma acc enter data copyin(Dts.t[:1])

person Smoden    schedule 27.07.2020    source источник


Ответы (1)


Согласно стандарту OpenACC, редукционные переменные не могут быть членами составной переменной. Самый простой способ обойти это ограничение — использовать локальную скалярную переменную, а затем присвоить результат члену структуры.

Что-то типа:

  double tmax;
  ...
  tmax = Dts->t;
  #pragma acc parallel loop collapse(3) reduction(max:tmax) present(Dts) 
        for (k = KBEG; k <= KEND; k++){
        for (j = JBEG; j <= JEND; j++){
        for (i = IBEG; i <= IEND; i++){
          tmax = MAX(tmax, C_dt[k][j][i]);
         
        }}}
  Dts->t = tmax;

Если вам нужно значение Dts-›t на устройстве, либо добавьте его в директиву устройства обновления после назначения, либо поместите tmax в область данных, а назначение — в последовательные области.

 // best if you need the value of Dts->t on both the host and device
  double tmax;
  ...
  tmax = Dts->t;
  #pragma acc parallel loop collapse(3) reduction(max:tmax) present(Dts) 
        for (k = KBEG; k <= KEND; k++){
        for (j = JBEG; j <= JEND; j++){
        for (i = IBEG; i <= IEND; i++){
          tmax = MAX(tmax, C_dt[k][j][i]);
         
        }}}
  Dts->t = tmax;
  #pragma acc update device(Dts->t)

or

  // best if you only need the value of Dts->t on the device
  double tmax;
  ...
  #pragma acc data create(tmax) 
  {
  #pragma acc serial present(Dts)
  {
  tmax = Dts->t;
  }
  #pragma acc parallel loop collapse(3) reduction(max:tmax) present(Dts) 
        for (k = KBEG; k <= KEND; k++){
        for (j = JBEG; j <= JEND; j++){
        for (i = IBEG; i <= IEND; i++){
          tmax = MAX(tmax, C_dt[k][j][i]);
         
        }}}
  #pragma acc serial present(Dts)
  {
  Dts->t = tmax;
  }
  }
person Mat Colgrove    schedule 27.07.2020