Παράλληλη Επεξεργασία — Ιούλιος 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, δεν έχει αντιπαραβληθεί με δεύτερη · εμπιστοσύνη λύτη: υψηλή
Προβλήματα στον κώδικα:
-
Το 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, ενώ είναι και περιττός υπολογισμός. -
Λείπει συγχρονισμός μετά τη δημιουργία των tasks.
Η άθροισηs = a[0]; for (j=1; j<20; j++) s += a[j];μπορεί να διαβάσει ταa[j]πριν ολοκληρωθούν τα tasks που τα γράφουν. Χρειάζεται#pragma omp taskwait(ήtaskgroup) πριν την ανάγνωση του πίνακα. -
Το
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 και υπολογίζει παράλληλα το άθροισμα.