Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

Καλησπέρα σας,

Προσπαθώ να βελτιστοποιήσω  και να παραλληλοποιήσω ένα πρόγραμμα που προσομοιώνει την λειτουργία ενός δικτύου νευρώνων του εγκεφάλου. Σας παραθέτω τον κώδικα υπό μορφή αρχείου λόγο του μεγέθους του(περιπου 400 γραμμές).

main.c

Συγκεκριμένα για την βελτιστοποίηση χρειάζεται να γίνουν οι εξής αλλαγές :

1) Ταχύτερη αντιγραφή διανύσματος στο διάνυσμα .

Επεξεργασμένος κώδικας : antigrafes.c

2)Αναδιοργάνωση υπολογισμών.

Επεξεργασμένος κώδικας : anadiorganwsi.c

3)Χρήση μιας συνάρτησης της βιβλιοθήκης BLAS για ταχύτερο υπολογισμό αλγεβρικών πράξεων.

Επεξεργασμένος κώδικας : blas.c

Το κύριο πρόβλημα που αντιμετωπίζω είναι στο ερώτημα 2 αφού μετά τις απαιτούμενες αλλαγές το πρόγραμμα εκτελείται πιο αργά.(Αν υπάρχει κάποια πρόταση για κάποιο άλλο ερώτημα είναι ευπρόσδεκτη.)

Υ.Γ. Συγγνώμη αν σας κούρασα είμαι καινούργιο σχετικά μέλος.. Αν υπάρχει κάποιο tutorial (στα ελληνικά κατά προτίμηση για OMP θα ήμουν ευγνώμων.

Δημοσ.

Αδερφέ, δεν νομίζω να σου λύσει κανείς την άσκηση. 

Παρέθεσε ποιο ακριβώς είναι το πρόβλημά σου και είναι πιο πιθανό να βρεις βοήθεια. 

Δημοσ. (επεξεργασμένο)

Την λύση της άσκησης την έχω προσθέσει στα τμήματα με ετικέτες "επεξεργασμένος κώδικας"(οπότε δεν περιμένω λύση :D). Αλλά οκ αναδιατυπώνω την ερώτηση.

Έχω αυτό το κομμάτι κώδικα όπου  uplus, u, διανύσματα μεγέθους(n) και sigma μητρώο μεγέθους(n*n).Συγκεκριμένα τα στοιχεία του έχουν τιμές 0.7 και 0 .

for (it = 0; it < itime; it++) {
        /*
         * Iteration over elements.
         */
        for (i = 0; i < n; i++) {
            uplus = u + dt * (mu - u);
            sum = 0.0;
            /*
             * Iteration over neighbouring neurons.
             */
            for (j = 0; j < n; j++)
                sum += sigma[i * n + j] * u[j] - sigma[ i * n + j ] * u ;
           
            uplus += dt * sum / divide;
        }

}

Οπότε για να μην γινεται σε κάθε επανάληψη υπολογισμός του υποαθροίσματος sigma[ i * n + j ] * u ο κώδικας που δημιούργησα έχει την εξής μορφή :

 /*
     * Computation of Svector elements.
     */
    for(i = 0 ; i < n ; i++)
        for(j = 0 ; j < n ; j++)
            Svector += sigma[i * n + j ] ;
    /*
     * Temporal iteration.
     */
    gettimeofday(&global_start, NULL);
    for (it = 0; it < itime; it++) {
        /*
         * Iteration over elements.
         */
        for (i = 0; i < n; i++) {
            uplus = u + dt * (mu - u);
            sum = 0.0;
            /*
             * Iteration over neighbouring neurons.
             */
            for (j = 0; j < n; j++) {
                sum += sigma[i * n + j] * u[j] ;
            }
            /*
             * Substrasction of the former sigma[i * n + j] *u
             * out of sum.
             */
            uplus += dt * (sum - Svector * u) / divide;

Τρέχοντας λοιπόν αυτόν τον κώδικα περίμενα μικρότερο χρόνο εκτέλεσης σε σχέση με τον προηγούμενο . Αυτό ωστόσο δεν συνέβη και εκεί ακριβώς έγκειται το πρόβλημα.

 

Επεξ/σία από proandy
παραμόρφωση κώδικα.
Δημοσ.

Εάν με τη λέξη "μητρώο" εννοείς matrix, τότε αυτός γίνεται update ή είναι σταθερός;

Από ό,τι βλέπω και υποψιάζομαι, λογικά ο καθαυτός κώδικας που τρέχει (μετά το optim του compiler) δεν θα είναι και τόσο διαφορετικός. 

Αλήθεια, γιατί απλά δεν κάνεις dot product με BLAS;

Δημοσ. (επεξεργασμένο)
1 ώρα πριν, Fortistis είπε

Εάν με τη λέξη "μητρώο" εννοείς matrix, τότε αυτός γίνεται update ή είναι σταθερός;

Από ό,τι βλέπω και υποψιάζομαι, λογικά ο καθαυτός κώδικας που τρέχει (μετά το optim του compiler) δεν θα είναι και τόσο διαφορετικός. 

Αλήθεια, γιατί απλά δεν κάνεις dot product με BLAS;

Αρχικά ναι, με την λέξη μητρώο εννοώ το matrix. H CBLAS  χρησιμοποιείται στο 3ο υποερώτημα ενώ στο αρχείο με το όνομα blas.c .Στο δεύτερο ερώτημα ζητείται κάποιοι σταθεροι όροι που υπολογίζονται ξανά και ξανα μεσα στα loops απλά να υπολογιστουν εκτος των loops και να χρησιμοποιήθουν σαν σταθερες μεταβλητές.Το matrix (μητρώο) sigma είναι σταθερό μητρώο καθόλη την διάρκεια του προγράμματος και αναπαριστα σε καθε γραμμή την σχέση ενος νευρώνα με τους γείτονες σε αυτον νευρώνες.

 

1 ώρα πριν, k33theod είπε

Εγώ βλέπω στο 1ο κομμάτι n**2*itime πράξεις και στο 2ο n**4*itime, εκτός αν χάνω κανένα άγκιστρο  😀

Που σημαίνει ότι ειναι πολύ λογικό να κάνει περισσοτερο χρόνο υποθέτω.Αν με κάποιο τρόπο γίνεται να ποστάρω τον κώδικα με πιο ευαναγνωστο τρόπο είμαι ανοιχτός σε προτάσεις.

 

Επεξ/σία από proandy
Δημοσ.
 for (it = 0; it < itime; it++) {
        /*
         * Iteration over elements.
         */
        for (i = 0; i < n; i++) {
            uplus = u + dt * (mu - u);
            sum = 0.0;
            /*
             * Iteration over neighbouring neurons.
             */
            for (j = 0; j < n; j++)
                sum += sigma[i * n + j] * u[j] - sigma[ i * n + j ] * u ;
           
            uplus += dt * sum / divide;
        }

} 
/*
     * Computation of Svector elements.
     */
    for(i = 0 ; i < n ; i++)
        for(j = 0 ; j < n ; j++)
            Svector[i] += sigma[i * n + j ] ;
    /*
     * Temporal iteration.
     */
    gettimeofday(&global_start, NULL);
    for (it = 0; it < itime; it++) {
        /*
         * Iteration over elements.
         */
        for (i = 0; i < n; i++) {
            uplus[i] = u[i] + dt * (mu - u[i]);
            sum = 0.0;
            /*
             * Iteration over neighbouring neurons.
             */
            for (j = 0; j < n; j++) {
                sum += sigma[i * n + j] * u[j] ;
            }
            /*
             * Substrasction of the former sigma[i * n + j] *u[i]
             * out of sum.
             */
            uplus[i] += dt * (sum - Svector[i] * u[i]) / divide;
            /*
             * Set uplus[i] = 0 if uplus[i] > uth
             */
            if (uplus[i] > uth) {
                uplus[i] = 0.0;
                /*
                 * Calculate omega's.
                 */
                if (it >= ttransient) {
                    omega1[i] += 1.0;
                }
            }
        }
        /*
         * Update network elements.
         */
        temp = u ;
        u = uplus ;
        uplus = temp ;
        /*
         * Print out of results.
         */

Στην μπάρα υπάρχει ένα κουμπί που έχει για σύμβολο <> αυτό το χρησιμοποιείς για να βάλεις κώδικα.

Αρχικά αυτό που ειπώθηκε ότι η πολυπλοκότητα πλέον έγινε O(n^4 * itime) είναι λάθος αλλά όντως έγινε πιο αργό το πρόγραμμα σου γιατί από O(n^2 * itime) έγινε O(n^2 * itime + n^2) που ναι μεν "ισοδυναμεί" με το αρχικό ασυμπτωτικά δεν παυεί να είναι extra χρόνος.
 

Έβγαλες τον υπολογισμό από έξω αλλά ουσιαστικά δεν κέρδισες τίποτα γιατί τον κάνεις έτσι και αλλιώς.  Επίσης ο κώδικας που έχεις postάρει σε σχέση με τα αρχεία είναι διαφορετικό και αυτό μπερδεύει κόσμο.

Δημοσ.
//Arxikopoihsh sigma.
s_min = 0.7 ;
s_max = 0.7 ;
for (i = 0; i < r; i++) {
        for (j = 0; j < i + r + 1; j++) {
            sigma[i * n + j] = s_min + (s_max - s_min) * drand48();
        }
        for (j = n - r + i; j < n; j++) {
            sigma[i * n + j] = s_min + (s_max - s_min) * drand48();
        }
    }

    for (i = r; i < n - r; i++) {
        for (j = 0; j < 2 * r + 1; j++) {
            sigma[i * n + j + i - r]  = s_min + (s_max - s_min) * drand48();
        }
    }

    for (i = n - r; i < n; i++) {
        for (j = 0; j < i - n + r + 1; j++) {
            sigma[i * n + j] = s_min + (s_max - s_min) * drand48();
        }
        for (j = i - r; j < n; j++) {
            sigma[i * n + j] = s_min + (s_max - s_min) * drand48();
        }
    }
7 ώρες πριν, kaliakman είπε

 

Αυτή είναι η αρχικοποίηση του sigma. Κάθε γραμμή του sigma στο στοιχείο της κύριας διαγωνίου έχει την αναπαράσταση του νευρώνα που ασχολούμαστε ενώ δεξια και αριστερά αυτού έχει τους γείτονες νευρώνες του (δηλ. νευρώνες που έχουν άμμεση σύνδεση με αυτόν) αυτοί λοιπον έχουν τιμή 0.7 ενώ οι υπόλοιποι έχουν 0.Πχ για n = 5(όπου n νευρώνες) και r =2 (όπου r οι γείτονες νευρώνες) o sigma έχει την εξής μορφή
0.7          0.7            0            0              0.7
0.7          0.7            0.7         0                0
0              0.7            0.7          0.7           0
0              0               0.7          0.7           0.7
0.7               0             0           0.7           0.7

Αυτό που σκέφτηκα για να κάνω το πρόγραμμα να τρέχει πιο γρήγορα ειναι στο άθροισμα

sum += sigma[i * n + j] * u[j] - sigma[ i * n + j ] * u ;
να απομονώσω το sigma[ i * n + j ] * u ;
και να γίνει ο υπολογισμός του ως εξής εφόσον sigma σταθερός καθ' όλη την διάρκεια του προγράμματος
x = (2 * r + 1) * 0.7 ; αλλα μου φαίνεται πολύ μπακάλικο αυτο..
9 ώρες πριν, kaliakman είπε

 for (it = 0; it < itime; it++) {
        /*
         * Iteration over elements.
         */
        for (i = 0; i < n; i++) {
            uplus = u + dt * (mu - u);
            sum = 0.0;
            /*
             * Iteration over neighbouring neurons.
             */
            for (j = 0; j < n; j++)
                sum += sigma[i * n + j] * u[j] - sigma[ i * n + j ] * u ;
           
            uplus += dt * sum / divide;
        }

} 

/*
     * Computation of Svector elements.
     */
    for(i = 0 ; i < n ; i++)
        for(j = 0 ; j < n ; j++)
            Svector[i] += sigma[i * n + j ] ;
    /*
     * Temporal iteration.
     */
    gettimeofday(&global_start, NULL);
    for (it = 0; it < itime; it++) {
        /*
         * Iteration over elements.
         */
        for (i = 0; i < n; i++) {
            uplus[i] = u[i] + dt * (mu - u[i]);
            sum = 0.0;
            /*
             * Iteration over neighbouring neurons.
             */
            for (j = 0; j < n; j++) {
                sum += sigma[i * n + j] * u[j] ;
            }
            /*
             * Substrasction of the former sigma[i * n + j] *u[i]
             * out of sum.
             */
            uplus[i] += dt * (sum - Svector[i] * u[i]) / divide;
            /*
             * Set uplus[i] = 0 if uplus[i] > uth
             */
            if (uplus[i] > uth) {
                uplus[i] = 0.0;
                /*
                 * Calculate omega's.
                 */
                if (it >= ttransient) {
                    omega1[i] += 1.0;
                }
            }
        }
        /*
         * Update network elements.
         */
        temp = u ;
        u = uplus ;
        uplus = temp ;
        /*
         * Print out of results.
         */

Στην μπάρα υπάρχει ένα κουμπί που έχει για σύμβολο <> αυτό το χρησιμοποιείς για να βάλεις κώδικα.

Αρχικά αυτό που ειπώθηκε ότι η πολυπλοκότητα πλέον έγινε O(n^4 * itime) είναι λάθος αλλά όντως έγινε πιο αργό το πρόγραμμα σου γιατί από O(n^2 * itime) έγινε O(n^2 * itime + n^2) που ναι μεν "ισοδυναμεί" με το αρχικό ασυμπτωτικά δεν παυεί να είναι extra χρόνος.
 

Έβγαλες τον υπολογισμό από έξω αλλά ουσιαστικά δεν κέρδισες τίποτα γιατί τον κάνεις έτσι και αλλιώς.  Επίσης ο κώδικας που έχεις postάρει σε σχέση με τα αρχεία είναι διαφορετικό και αυτό μπερδεύει κόσμο.

Νόμιζα ότι απορροφάται από τον ασυμπτωτικό συμβολισμό Ο() το σταθερό μέρος άλλα αυτό ισχύει μόνο στην θεωρία μάλλον.. Ο κώδικας είναι αρκετά μεγάλος σε μέγεθος και για αυτό δεν τον πόσταρα ολόκληρο κατόπιν συμβουλής του φίλου foritisti .. Τώρα όσο αναφορά  τα αρχεία το πρόβλημα υπάρχει στο αρχείο με ονομα anadiorganosi.c είναι λογικό να διαφέρουν μεταξύ τους αφού σε κάθε αρχείο έχω κάνει και μια βελτιστοποιήση  ..

Δημοσ. (επεξεργασμένο)
2 ώρες πριν, proandy είπε

//Arxikopoihsh sigma.
s_min = 0.7 ;
s_max = 0.7 ;
for (i = 0; i < r; i++) {
        for (j = 0; j < i + r + 1; j++) {
            sigma[i * n + j] = s_min + (s_max - s_min) * drand48();
        }
        for (j = n - r + i; j < n; j++) {
            sigma[i * n + j] = s_min + (s_max - s_min) * drand48();
        }
    }

    for (i = r; i < n - r; i++) {
        for (j = 0; j < 2 * r + 1; j++) {
            sigma[i * n + j + i - r]  = s_min + (s_max - s_min) * drand48();
        }
    }

    for (i = n - r; i < n; i++) {
        for (j = 0; j < i - n + r + 1; j++) {
            sigma[i * n + j] = s_min + (s_max - s_min) * drand48();
        }
        for (j = i - r; j < n; j++) {
            sigma[i * n + j] = s_min + (s_max - s_min) * drand48();
        }
    }

Αυτή είναι η αρχικοποίηση του sigma. Κάθε γραμμή του sigma στο στοιχείο της κύριας διαγωνίου έχει την αναπαράσταση του νευρώνα που ασχολούμαστε ενώ δεξια και αριστερά αυτού έχει τους γείτονες νευρώνες του (δηλ. νευρώνες που έχουν άμμεση σύνδεση με αυτόν) αυτοί λοιπον έχουν τιμή 0.7 ενώ οι υπόλοιποι έχουν 0.Πχ για n = 5(όπου n νευρώνες) και r =2 (όπου r οι γείτονες νευρώνες) o sigma έχει την εξής μορφή
0.7          0.7            0            0              0.7
0.7          0.7            0.7         0                0
0              0.7            0.7          0.7           0
0              0               0.7          0.7           0.7
0.7               0             0           0.7           0.7

Αυτό που σκέφτηκα για να κάνω το πρόγραμμα να τρέχει πιο γρήγορα ειναι στο άθροισμα


sum += sigma[i * n + j] * u[j] - sigma[ i * n + j ] * u ;
να απομονώσω το sigma[ i * n + j ] * u ;
και να γίνει ο υπολογισμός του ως εξής εφόσον sigma σταθερός καθ' όλη την διάρκεια του προγράμματος
x = (2 * r + 1) * 0.7 ; αλλα μου φαίνεται πολύ μπακάλικο αυτο..

Νόμιζα ότι απορροφάται από τον ασυμπτωτικό συμβολισμό Ο() το σταθερό μέρος άλλα αυτό ισχύει μόνο στην θεωρία μάλλον.. Ο κώδικας είναι αρκετά μεγάλος σε μέγεθος και για αυτό δεν τον πόσταρα ολόκληρο κατόπιν συμβουλής του φίλου foritisti .. Τώρα όσο αναφορά  τα αρχεία το πρόβλημα υπάρχει στο αρχείο με ονομα anadiorganosi.c είναι λογικό να διαφέρουν μεταξύ τους αφού σε κάθε αρχείο έχω κάνει και μια βελτιστοποιήση  ..

Το ξαναλέω: Ήταν O(n^2 * itime)  και το έκανες O(n^2 * itime + n^2)  που ναι μεν ασυμπτωτικά ισούται με O(n^2 * itime) αλλά στην πραγματικότητα του αύξησες την πολυπλοκότητα αντί να την μειώσεις. Το θέμα είναι να ρίξεις το n^2*itime για να μειώσεις τον χρόνο. Αρχικά μπορείς να το κάνεις compile με optimizations(αν δεν το κάνεις ήδη) και να αφήσεις τον compiler να κάνει διάφορα.

Επεξ/σία από kaliakman
  • Like 1
Δημοσ.

Μπορείς να δοκιμάσεις το όρισμα -Ofast εάν χρησιμοποιείς GCC η clang (δεν ξέρω για άλλους compilers).

Ουσιαστικά είναι -O3 συν μερικά άλλα optimizations που δεν είναι απαραίτητως standard-compliant, αλλά μπορεί να είναι οκ για την χρήση σου.

  • Like 1
Δημοσ.

Π.χ., εφόσον το μόνο που μεταβάλεται στον υπολογισμό του sum είναι το i, τότε μπορείς να προϋπολογίσεις ότι χρειάζεσαι και να μην το κάνεις για κάθε i. 

Εάν παρατήρησα σωστά, μόνο το uplus αλλάζει και αλλάζει βάσει σταθερών μεγεθών.

Αντί να κάνεις σειριακό υπολογισμό των τιμών του uplus, υπολόγισε από πριν ό,τι χρειάζεσαι (θα φας παραπάνω μνήμη) και χρησιμοποίησέ τα για το uplus.

  • Like 1
Δημοσ.

Παιδιά αρχικά συγγνώμη για την αναστάτωση που δημιουργώ και σας ευχαριστώ  τον καθένα που ασχολείται με το προβλημα που αντιμετωπίζω. Αρχικά κατάλαβα ότι εχω αυξήσει την πολυπλοκότητα του προγράμματος αρα σωστά το προγραμμα έχει περισσότερο χρόνο εκτέλεσης. Δυστυχώς η άσκηση δεν ζητάει να κάνεις βελτιστοποίηση μέσω διαφόρων flags κατα το compile αν και το έχω δοκιμάσει απο περιέργεια και όντως έχει αρκετή διαφορά σε σχέση με απλό  compile. Η άσκηση ζητά στον υπολογισμό του sum όπως είπε και ο fortistis να υπολογιστεί με διαφορετικό τρόπο το υποάθροισμα sigma [i * n +j] * u εφόσον το matrix sigma είναι σταθερό καθ'όλη την διάρκεια του προγράμματος και να βγεί απο το loop με μεταβλητή ελέγχου j ..Το uplus αντιγράφεται στο u μετά οπότε αλλαζουν και τα δύο. Anyway επειδή για να γίνει αυτή η βελτιστοποίηση πρέπει κανείς να κατανοήσει καλά το πως αλληλεπιδρούν τα στοιχεία του προγράμματος μεταξύ τους (πράγμα που απαιτεί πολύ χρόνο λόγο όγκου προγράμματος) θα ήταν καλύτερο να μην το συνεχίσουμε το συγκεκριμένο thread μιας και δεν νομίζω να βγάλουμε άκρη.
Συγγνώμη και πάλι και ευχαριστώ πολύ για την βοήθεια.

 

Δημοσ. (επεξεργασμένο)

Λοιπόν παιδιά κάλιο αργά παρά ποτέ.. Βρήκα την λύση στο πρόβλημα και την παραθέτω για όποιον ίσως προσπάθησε και δεν τα κατάφερε.. Ανακεφαλαιώνοντας αυτό που έπρεπε να γίνει από την άσκηση ήταν βελτιστοποίηση  ενός πολλαπλασιασμού μητρώου με διάνυσμα χωρίς χρήση έτοιμης συνάρτησης από κάποια βιβλιοθήκη (πχ BLAS) συγκεκριμένα έπρεπε να υπολογιστεί το sigma[ i * n + j] * u[ i ]  μέσα στον βρόχο j . Παρατηρώντας, το u[ i ] είναι ανεξάρτητο του j οπότε δεν θα μας πείραζε αν βρίσκαμε κάποιο τρόπο να το βγάλουμε από τον βρόχο j ωστόσο αυτό θα αλλοίωνε κατά πολύ αυτό που θέλουμε να υπολογίσουμε δηλαδή τα επιμέρους εσωτερικά γινόμενα της i - οστής γραμμής του sigma με το i - οστό στοιχείο του u.. Γνωρίζουμε όμως για τον sigma την μορφή του δηλαδή ότι έχει ίσο αριθό 0.7 σε κάθε γραμμή και τα υπόλοιπα στοιχεία της γραμμής είναι 0 .Επομένως αφού το εσωτερικό γινόμενο έχει την μορφή  sigma[0] [0] * u[0] + sigma [0] [1] * u[0] + ......+ sigma [0][n] * u[0] τα μηδενικά στοιχεία του sigma μας είναι αδιάφορα αφού δεν το επηρεάζουν  0 +  x = x και αν βγάλουμε κοινό παράγοντα το u[0] μας μένει (sigma [0][0] + ..... + sigma[0][1]) * u[0] .Επομένως αν βρούμε το άθροισμα μιας γραμμής του sigma  (και εφόσον έχουν όλες το ίδιο άθροισμα ίδιος αριθμός 0.7) θα βγάλουμε τον ζητούμενο υπολογισμό έξω από τον βρόχο θα το υπολογίσουμε ΜΙΑ  φορά έξω από τον βρόχο it  και θα το χρησιμοποιήσουμε σαν σταθερά στην συνέχεια .Οπότε ο κώδικας μας έχει ως εξής :

 for(i = 0 ; i <  n ; i++)
    {
        x += sigma[i];
    }
     /*
     * Temporal iteration.
     */
    gettimeofday(&global_start, NULL);
    for (it = 0; it < itime; it++) {
        /*
         * Iteration over elements.
         */
        for (i = 0; i < n; i++) {
            uplus[i] = u[i] + dt * (mu - u[i]);
            sum = 0.0;
            /*
             * Iteration over neighbouring neurons.
             */
            for (j = 0; j < n; j++) {
                sum += sigma[i * n + j] * u[j]  ;
            }
            /*
             * Substrasction of the former sigma[i * n + j] *u[i]
             * out of sum.
             */
            uplus[i] += dt * (sum - x * u[i]) / divide;
            /*
             * Set uplus[i] = 0 if uplus[i] > uth
             */
            if (uplus[i] > uth) {
                uplus[i] = 0.0;
                /*
                 * Calculate omega's.
                 */
                if (it >= ttransient) {
                    omega1[i] += 1.0;
                }
            }
        }
        /*
         * Update network elements.
         */
        temp = u ;
        u = uplus ;
        uplus = temp ;
        /*
         * Print out of results.
         */

Τώρα αυτό που είχα σκεφτεί αρχικά και δεν έβγαινε είναι το εξής ακόμα δεν γνωρίζω γιατί αλλά υποψιάζομαι ότι ήταν θέμα ακρίβειας των υπολογισμών (χωρίς να είμαι καθόλου σίγουρος) i-οστή γραμμή του sigma αναπαριστά την σχέση του i-οστού νευρώνα με τους γύρω του (πως ακριβώς το κάνει αυτό??) βάζοντας στο θέση του νευρώνα αυτού την τιμή 0.7 όπως και σε r θέσεις δεξιά του και άλλες r αριστερά από αυτόν (αν δεν υπάρχουν αρκετές θέσεις αριστερά πάει στην πρώτη θέση από δεξια και το αντίστροφο). Οπότε αυτό που σκέφτηκα ήταν να βρώ το άθροισμα της γραμμής χωρίς καμία loop κάνοντας το εξής  σε μία μεταβλητή  x να εκχωρήσω το (2 * r + 1) * 0.7 και στην συνέχεια να το αντικαταστήσω με τον ίδιο τρόπο όπως και παραπάνω..

Επεξ/σία από proandy
Δημοσ. (επεξεργασμένο)

Για το "αλγοριθμικό" κομμάτι δεν έχω να σχολιάσω κάτι γιατί δεν ξέρω τι κάνει ακριβώς και πώς μπορείς να γλυτώσεις πράξεις δεδομένου οτι η είσοδος έχει μια συγκεκριμένη μορφή. Αλλά στο καθαρό υπολογιστικό κομμάτι μπορεις να κάνεις αρκέτα.

Το body του itime for loop τρέχει πολύ εύκολα παράλληλα με openmp (αν σας το επιτρέπουν). Χρειάζεσαι ένα μεγάλο parallel region για τα i από 0 μέχρι n και barrier μεταξύ των for επειδή στο δεύτερο for γράφεις στον u[] τον uplus[]. Το ίδιο και όταν  πειράξεις το omega[]. 

Βέβαια έτσι φτιάχνεις και καταστρέφεις τα νήματα σε κάθε επανάληψη του itime loop που δεν είναι βέλτιστο. Για να το αποφύγεις αυτό, πρέπει να φτιάξεις δικά σου νήματα που πάλι τρέχουν παράλληλα το body του main itime loop σε ένα while(1), αλλά βάζεις δύο barriers (NUM_THREADS + 1) για να ελέγχεις πότε τρέχουν (ένα στην αρχή του while(1) και ένα στο τέλος). Από το  main thread τρέχεις το itime loop και κλειδώνεις/ξεκλειδώνεις τα input/output barriers των νημάτων.

Επίσης μπορείς να βγάλεις τη διαίρεση με το divide αφού δεν αλλάζει κατά τη διάρκεια του υπολογισμού. Υπολογίζεις μια φορά το αντίστροφο του divide και κάνεις πολλαπλασιασμό αντί για διαίρεση που είναι πιο γρήγορο.

Με την ίδια λογική μπορείς να το μετατρέψεις να τρέχει και στη GPU με CUDA πχ ή με OpenCL, που εκεί τρέχεις εκατομμύρια threads ταυτόχρονα.

Επεξ/σία από ChRis6
  • Like 1

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...