2013-07-10 21 views
7

Tworzę podstawowy sprawdzian liczby liczb pierwszych oparty na C - determine if a number is prime, ale z wykorzystaniem OpenMP.Błąd kompilatora "nieprawidłowy controlling" przy użyciu OpenMP

int isPrime(int value) 
{ 
    omp_set_num_threads(4); 

    #pragma omp parallel for 
    for(int j = 2; j * j <= value; j++) 
    { 
    if (value % j == 0) return 0; 
    } 
    return value; 
} 

Podczas kompilacji z -fopenmp, GCC wersja 4.7.2 jest erroring, stwierdzając invalid controlling predicate względem pętli for.

Wygląda na to, że ten błąd jest spowodowany przez j do kwadratu w pętli for. Czy istnieje sposób można obejść to i nadal osiągnąć pożądaną wydajność z algorytmu?

+0

czy jesteś pewien, że instrukcja return jest dozwolona w konstrukcie pętli open mp? – alexbuisson

+0

Niestety, równoległość pętli z OpenMP nie pomoże w testowaniu pojedynczego prime z podziałem próbnym. Można go jednak skutecznie wykorzystać do testowania wielu liczb pierwszych przy użyciu podziału próbnego. Jednakże, aby znaleźć listę liczb pierwszych, polecam Sito Eratostenesa. Oto wersja korzystająca z OpenMP http://create.stephan-brumme.com/eratosthenes/ –

+0

Również w twojej funkcji 'isPrime' zalecam używanie' j <= j/value' zamiast 'j * j <= value' który może przepełnić http://rosettacode.org/wiki/Primality_by_trial_division#C –

Odpowiedz

8

return nie jest dozwolone wewnątrz pętli, ponieważ spowoduje to wyjście przed nawiasami klamrowymi.

Uwaga definicja podana poniżej:

Od spec OpenMP v2.5, 1.2.2 terminologia język OpenMP, p2: 17-

zorganizowany blok - dla C/C++, wykonywalny oświadczenie , prawdopodobnie związek, z pojedynczym wpisem u góry i jednym zjazdem u dołu .

Blok strukturalny rozpoczyna się od otwartego { i kończy się zamknięciem }. return jest zawarty w tych szelek, więc ten program jest niezgodny również definicję OpenMP na strukturyzowany bloku, ponieważ ma dwa wyjścia (jedno na return i jeden na wyjeździe przez nawias)

OpenMP miejscach pięć następujących ograniczeń na których pętle mogą być gwintowane:

  • Zmienna pętli musi być typu ze znakiem ze znakiem. Niepodpisane liczby całkowite, , takie jak DWORD, nie będą działać.
  • Operacja porównania muszą być w loop_variable postaci <, <=, >, lub >= loop_invariant_integer
  • Trzeci ekspresji lub przyrost część do pętli musi być liczbą całkowitą, dodatek lub całkowite odjęcie i pętli niezmienna wartość.
  • Jeżeli porównanie działania jest < lub <= zmienna pętli musi przyrost w każdej iteracji, i odwrotnie, jeżeli porównanie działania jest > lub >= zmienna pętli należy zmniejszyć w każdym iteracji.
  • Pętla musi być blokiem podstawowym, co oznacza, że ​​nie ma żadnych skoków od środka do pętla na zewnątrz są dozwolone, z wyjątkiem instrukcji wyjścia , która kończy całą aplikację. Jeśli używane są instrukcje "goto" lub "break", muszą one przeskoczyć w pętli, a nie poza nią: . To samo dotyczy obsługi wyjątków; wyjątki muszą zostać przechwycone w pętli .
+0

Nie rozumiem, dlaczego zmienna pętli musi być podpisana. Co zrobić, jeśli potrzebujesz liczby całkowitej większej niż 8 bajtów ze znakiem? – Nubcake

2

Zgodnie ze standardem OpenMP (§ 2.5.1, s.40), przy czym dopuszczalne formy kontrolnego predykatu pętli for są:

  • var relacyjnej OP B i
  • b relacyjnej OP var

Używanie j * j <= value stanowi wyraźne naruszenie tego wymogu. Uzasadnieniem jest to, że wymaga kompilator do emitowania kodu, który oblicza pierwiastek kwadratowy liczby całkowitej z value w czasie wykonywania, z tym ostatnim jest niezdefiniowana dla niektórych wartości value, w szczególności dla negatywnych.

Można zastąpić j * j <= value z j <= sqrt_value, gdzie sqrt_value jest liczbą całkowitą pierwiastek kwadratowy value, ale potem przyjdzie problemu z posiadaniem alternatywną drogę wyjścia w strukturze bloku wewnątrz pętli. Niestety, w tym przypadku nie ma łatwego rozwiązania, ponieważ OpenMP nie obsługuje przedwczesnego zakończenia równoległych pętli.

Powiązane problemy