Μετάβαση στο περιεχόμενο

Παράλληλη Επεξεργασία — Ιούλιος 2023 — Exam Question I (αγγλικά)

Μεταγραφή από το 9acba9fcf4c6629ffd5add398d3bfd48.png· το aa.PNG είναι δεύτερη (μερική) εικόνα του ίδιου ερωτήματος.

9acba9fcf4c6629ffd5add398d3bfd48.png

Exam Question I

Identify and explain any issues in the following OpenMP code. Propose a solution.

int a[20], s;
#pragma omp parallel num_threads(10)
{
    for (int i = 0; i < 20; i++)
    {
        #pragma omp task
        {
            a[i] = func();
        }
    }

    s = a[0];
    for (int j = 1; j < 20; j++) s += a[j];
}

Σημείωση: η εικόνα έχει αριθμημένες γραμμές κώδικα (1–14)· η αρίθμηση δεν μεταφέρεται στο παραπάνω μπλοκ.

Λύσεις (⚪ AI, μη επαληθευμένο)

Κατάσταση: ⚪ AI, μη επαληθευμένο Πηγή: λύσεις AI (deepseek-flash), ανεξάρτητη επανάληψη και αντιπαραβολή· καμία δεν έχει ελεγχθεί από άνθρωπο

Προσοχή

Λύση από AI — ελέγξτε την· δεν έχει επαληθευτεί από άνθρωπο. Η ένδειξη «δύο λύσεις συμφωνούν» δεν σημαίνει ότι η απάντηση είναι σωστή.

AI λύσεις — 2023-07-en

Οι λύσεις γράφτηκαν από μοντέλα AI και δεν έχουν ελεγχθεί από άνθρωπο. Η αρίθμηση ακολουθεί το αρχείο θεμάτων.

Θέμα I (Exam Question I)

Αξιοπιστία: μία λύση AI, δεν έχει αντιπαραβληθεί με δεύτερη · εμπιστοσύνη λύτη: υψηλή

Προβλήματα στον κώδικα:

  1. Το loop δημιουργίας tasks εκτελείται από όλα τα threads.
    Το for (i = 0; i < 20; i++) βρίσκεται μέσα στο #pragma omp parallel χωρίς single ή κάποιο work-sharing construct. Έτσι και τα 10 threads εκτελούν ολόκληρο το loop και δημιουργούν από 20 tasks το καθένα (συνολικά 200 tasks). Αυτό προκαλεί πολλαπλές εγγραφές στο ίδιο a[i] και άρα data race στο a, ενώ είναι και περιττός υπολογισμός.

  2. Λείπει συγχρονισμός μετά τη δημιουργία των tasks.
    Η άθροιση s = a[0]; for (j=1; j<20; j++) s += a[j]; μπορεί να διαβάσει τα a[j] πριν ολοκληρωθούν τα tasks που τα γράφουν. Χρειάζεται #pragma omp taskwait (ή taskgroup) πριν την ανάγνωση του πίνακα.

  3. Το s είναι shared και ενημερώνεται ταυτόχρονα από πολλά threads.
    Όλα τα threads εκτελούν την άθροιση και γράφουν στο κοινό s χωρίς συγχρονισμό, προκαλώντας data race και λανθασμένο αποτέλεσμα. Πρέπει η άθροιση να γίνει από ένα thread ή να χρησιμοποιηθεί reduction(+:s).

Μια διορθωμένη λύση είναι η εξής:

int a[20], s = 0;

#pragma omp parallel num_threads(10)
{
    #pragma omp single
    {
        for (int i = 0; i < 20; i++) {
            #pragma omp task
            {
                a[i] = func();
            }
        }
        #pragma omp taskwait   // αναμονή για όλα τα child tasks
    }

    #pragma omp for reduction(+:s)
    for (int j = 0; j < 20; j++) {
        s += a[j];
    }
}

Στην παραπάνω λύση: - Μόνο ένα thread δημιουργεί τα tasks, άρα κάθε a[i] γράφεται μία φορά. - Το taskwait εξασφαλίζει ότι όλα τα tasks ολοκληρώθηκαν πριν διαβαστεί ο πίνακας. - Το reduction(+:s) αποφεύγει το data race στο s και υπολογίζει παράλληλα το άθροισμα.

✔ Επιβεβαίωσε · ✖ Βρήκα λάθος


✖ Βρήκα λάθος στη μεταγραφή