2015-05-16 11 views
7

Kiedy używam dyrektywy cancel (od OpenMP 4.0) do przerwania pętli równoległej w obrębie konstruktu parallel for, GCC 5.1 ostrzega" #pragma omp cancel dla 'wewnątrz' nowait 'dla konstrukcji " dla poniższego fragmentu.GCC 5.1 ostrzega o anulowaniu konstruktu w konstrukcji `parallel for`

const int N = 10000; 

int main() 
{ 
    #pragma omp parallel for 
    for (int i = 0; i < N; i++) { 
    #pragma omp cancel for // <-- here 
    } 
} 

http://coliru.stacked-crooked.com/a/de5c52da5a16c154

Aby obejść ten problem, kiedy podzielone na parallel + for konstruktów, GCC akceptuje kod cicho.

int main() 
{ 
    #pragma omp parallel 
    #pragma omp for 
    for (int i = 0; i < N; i++) { 
    #pragma omp cancel for 
    } 
} 

Ale nie wiem, dlaczego GCC ostrzega w poprzednim przypadku, ale konstrukcja nie ma klauzuli "nowait". OpenMP 4.0 API spec również mówi, że parallel for jest równa konstrukcji parallel + for.

2.10.1 Parallel Loop Construct

Description

The semantics are identical to explicitly specifying a parallel directive immediately followed by a for directive.

Czy zachowanie GCC jest prawidłowe? czy coś nie tak?

+4

Myślę, że GCC powinien emitować lepszy komunikat o błędzie. Kompilator Intel wyrzuca: "błąd: anuluj dla musi być ściśle zagnieżdżony w regionie" dla tego przypadku (co ma trochę więcej sensu). Chociaż 'parallel dla' i' parallel' po którym następuje 'for' są podobne, konstrukcja' cancel' pozwala tylko na jedną klauzulę ... metinks kompilator odczytuje klauzulę, po której następuje 'cancel' i sprawdza, co było obudową, w twoim pierwszym przykładzie jest to 'parallel for', a nie' for', stąd kompilator zgłasza ten błąd. Tylko moje 2 centy. – Sayan

+0

GCC ostrzega, Clang nie ostrzega, a ICC nie kompiluje się w pierwszym przypadku. Wszystkie trzy kompilatory kompilują się bez ostrzeżenia w drugim przypadku. Ciekawy. –

+0

@Sayan, nie jestem pewien, dlaczego komunikat o błędzie ICC jest lepszy niż ostrzeżenie GCC. Wydaje się, że Intel uważa, że ​​anulowanie nie ma miejsca w pętli for, która jest wyraźnie widoczna. Wygląda na to, że ten przypadek jest https://software.intel.com/en-us/articles/cdiag1159, dla którego kompilator podaje poprawny błąd. –

Odpowiedz

0

Domyślam się, że Twój kod

#pragma omp parallel for 
    for (int i = 0; i < N; i++) { 
    #pragma omp cancel for 
    } 

nie jest równoznaczne z

#pragma omp parallel 
    { 
    #pragma omp for 
    for (int i = 0; i < N; i++) { 
    #pragma omp cancel for 
    } 
    } //end of parallel region 

w tym ostatnim przypadku nie byłoby dwie bariery: jedna w końcu za i jeden na koniec równoległego regionu; coś równoważne:

#pragma omp parallel 
    { 
     #pragma omp for nowait 
     for (int i = 0; i < N; i++) { 
      #pragma omp cancel for 
     } 
     #pragma omp barrier 
    } // and here another implicit barrier 

ale myślę, że dla celów optymalizacji The compilter może próbować usunąć drugą unecessary barierę i generuje:

#pragma omp parallel 
    { 
     #pragma omp for nowait 
     for (int i = 0; i < N; i++) { 
      #pragma omp cancel for 
     } 
    } 

która jest bardziej „optymalna”, ale ma tę wadę ostrzec o konieczności wstawiania nowego i anulowania.

Powiązane problemy