Anfängerfrage in C / OpenMP: shared Variablen



  • Hey,

    ich bin neu und habe zu Beginn gleich mal eine Frage.
    Die "Hausaufgabe" ist in C ein Programm zu schreiben, welches in mehreren Tasks Zahlen summiert.
    Genutzt werden soll OpenMP.
    Da ich ein Neuling sowol in C als auch OpenMP bin, habe ich ein paar Schwierigkeiten.
    Nach langem probieren habe ich die Aufgabe lösen können, verstehe aber nicht, warum die Variablen ("links","rechts") shared sein müssen.
    Kann mir das jemand sagen?
    Hier meine Lösung:

    #include <omp.h>
    #include <stdio.h>
    
    int main(int argc, char **argv){
        int werte[] = {1,2,3,4,5};
        int groesse = 5;
    
        #pragma omp parallel
        {
            #pragma omp single
            printf("Ergebnis:%d\n",sum(werte, 0, groesse));
        }
    }
    
    int sum(int *werte, int vorlauf, int groesse) {
         int links;
         int rechts;
         if (groesse==1) return werte[vorlauf];
         #pragma omp task shared(links,rechts)
         links = sum(werte, vorlauf, groesse/2);
         #pragma omp task shared(links,rechts)
         rechts= sum(werte, vorlauf + groesse/2, groesse - groesse/2);
         #pragma omp taskwait
         return links+rechts;
    }
    

    Vielen Dank und Grüße!


  • Mod

    Es reicht, wenn jeweils nur die Variable shared ist, die in dem jeweiligen Task benutzt wird, also:

    int sum(int *werte, int vorlauf, int groesse) {
         int links;
         int rechts;
         if (groesse==1) return werte[vorlauf];
         #pragma omp task shared(links)
         links = sum(werte, vorlauf, groesse/2);
         #pragma omp task shared(rechts)
         rechts= sum(werte, vorlauf + groesse/2, groesse - groesse/2);
         #pragma omp taskwait
         return links+rechts;
    }
    

    Warum überhaupt shared? Das Ergebnis muss ja auch irgendwie nach draußen getragen werden. Das ist, was shared (unter anderem) macht.



  • Hallo.

    Du musst prinzipiell entscheiden ob eine variable shared oder private sein soll:

    private: mit dem Variablennamen wird eine neue Variable für jeden Thread bzw. Task in deinem Beispiel assoziiert - als technische Erklärung kannst du dir vorstellen, dass es eine neue Variablendeklaration gleichen Namens im Block eines Threads bzw. Tasks gibt.

    shared: mit dem Variablennamen bleibt die ursprüngliche Variable assoziiert - als technische Erklärung kannst du dir vorstellen, dass es dann in einem Thread bzw. Task einen Pointer auf die ursprüngliche Variable gibt.

    Was passiert mit private in deinem Beispiel? Innerhalb des Tasks gibt es eine neue Variable namens links bzw. rechts mit der die Berechnung prinzipiell erfolgen kann, aber nach dem Task (insbesondere nach dem taskwait) gibt es die Variable nicht mehr (sie existierte nur für die Lebensdauer des Tasks auf eben dessen Stack). Somit wäre der Rückgabewert 0.

    Was passiert mit shared? Innerhalb der beiden Tasks werden genau die Variablen verwendet, welche durch den Aufruf von sum() auf dem Stack abgelegt wurden. Das ist genau das Verhalten was du haben willst.

    Was passiert wenn du gar nichts sagst? Die nicht unbedingt intuitiven Regeln von OpenMP sorgen dafür, dass die Variablen links/rechts in ihren Tasks als firstprivate erscheinen, das ist private mit Initialisierung. Eben genau das was du nicht willst.

    VG, Christian


Log in to reply