DarthMoul
23-07-2004, 08:17
Αν υποθέσουμε ότι έχουμε να προσθέσουμε δύο ακεραίους. Πχ a = b + c;
Η CPU θα κάνει ένα αίτημα στον memory controller για την ανάκτηση της μεταβλητής b. Αν αυτή δεν υπάρχει μέσα στο L1 cache, τότε έχουμε την περίπτωση του cache miss. Κατόπιν ο memory controller θα την αναζητήσει στο L2 cache, στο L3 cache και στο τέλος στην μνήμη αν χρειαστεί. Το ίδιο θα κάνει και με την c. Αφού μεταφερθούν και οι δύο μεταβλητές μέσα σε κάποιους registers, θα γίνει η πρόσθεση.
Κατά την αναζήτηση των μεταβλητών στα caches και την μνήμη, η CPU αναγκάζεται να περιμένει τον memory controller, οπότε λέμε ότι έχουμε CPU stall. Το πόσο θα μας κοστίσει το cache miss εξαρτάται από την αρχιτεκτονική καθώς και από την ποιότητα και τον τύπο της μνήμης που χρησιμοποιεί το σύστημα μας. Συνήθως είναι από 21 μέχρι και 206 κύκλους μηχανής για P4EE και από από 16 εώς 101 για Athlon64. Με άλλα λόγια, στην παραπάνω περίπτωση, μπορεί να έχουμε μέχρι και 412 κύκλους μηχανής την CPU να κάθεται, περιμένοντας τον memory controller να φέρει τα περιεχόμενα των μεταβλητών από την μνήμη στους καταχωρητές για να γίνει μία πρόσθεση, της οποίας το κόστος είναι ένας μόνο κύκλος.
Για να αποφύγουμε το CPU stall, θα χρησιμοποιήσουμε ένα χαρακτηριστικό του memory controller που ονομάζεται data parallelism. Ο memory controller έχει την ικανότητα να δέχεται περισσότερα από ένα αιτήματα προς διεκπεραίωση. Συνεπώς για να μειώσουμε το stall αυτό που μπορούμε να κάνουμε variable preload. Πχ.
t = b;
t = c;
a = b + c;
Μπορεί να φαίνεται πιο χαζό και αργό, αλλά στην πραγματικότητα δεν είναι. Εδώ εκδίδουμε δύο αιτήματα προς τον memory controller για να διεκπεραιωθούν ταυτόχρονα. Όταν θα έρθει η ώρα της πρόσθεσης, οι μεταβλητές b και c θα βρίσκονται ήδη στο L1 cache. Το κόστος μεταφοράς τους όμως θα έχει κοστίσει μόνο 206 κύκλους μηχανής λόγω του παραλληλισμού και όχι 412 όπως πριν αν μιλάμε για Pentium.
Αυτά ισχύουν μόνο για μεμονωμένες μεταβλητές. Για πίνακες και memory blocks, ακολουθούμε άλλη τεχνική και θα την πούμε σε άλλο thread.
Η CPU θα κάνει ένα αίτημα στον memory controller για την ανάκτηση της μεταβλητής b. Αν αυτή δεν υπάρχει μέσα στο L1 cache, τότε έχουμε την περίπτωση του cache miss. Κατόπιν ο memory controller θα την αναζητήσει στο L2 cache, στο L3 cache και στο τέλος στην μνήμη αν χρειαστεί. Το ίδιο θα κάνει και με την c. Αφού μεταφερθούν και οι δύο μεταβλητές μέσα σε κάποιους registers, θα γίνει η πρόσθεση.
Κατά την αναζήτηση των μεταβλητών στα caches και την μνήμη, η CPU αναγκάζεται να περιμένει τον memory controller, οπότε λέμε ότι έχουμε CPU stall. Το πόσο θα μας κοστίσει το cache miss εξαρτάται από την αρχιτεκτονική καθώς και από την ποιότητα και τον τύπο της μνήμης που χρησιμοποιεί το σύστημα μας. Συνήθως είναι από 21 μέχρι και 206 κύκλους μηχανής για P4EE και από από 16 εώς 101 για Athlon64. Με άλλα λόγια, στην παραπάνω περίπτωση, μπορεί να έχουμε μέχρι και 412 κύκλους μηχανής την CPU να κάθεται, περιμένοντας τον memory controller να φέρει τα περιεχόμενα των μεταβλητών από την μνήμη στους καταχωρητές για να γίνει μία πρόσθεση, της οποίας το κόστος είναι ένας μόνο κύκλος.
Για να αποφύγουμε το CPU stall, θα χρησιμοποιήσουμε ένα χαρακτηριστικό του memory controller που ονομάζεται data parallelism. Ο memory controller έχει την ικανότητα να δέχεται περισσότερα από ένα αιτήματα προς διεκπεραίωση. Συνεπώς για να μειώσουμε το stall αυτό που μπορούμε να κάνουμε variable preload. Πχ.
t = b;
t = c;
a = b + c;
Μπορεί να φαίνεται πιο χαζό και αργό, αλλά στην πραγματικότητα δεν είναι. Εδώ εκδίδουμε δύο αιτήματα προς τον memory controller για να διεκπεραιωθούν ταυτόχρονα. Όταν θα έρθει η ώρα της πρόσθεσης, οι μεταβλητές b και c θα βρίσκονται ήδη στο L1 cache. Το κόστος μεταφοράς τους όμως θα έχει κοστίσει μόνο 206 κύκλους μηχανής λόγω του παραλληλισμού και όχι 412 όπως πριν αν μιλάμε για Pentium.
Αυτά ισχύουν μόνο για μεμονωμένες μεταβλητές. Για πίνακες και memory blocks, ακολουθούμε άλλη τεχνική και θα την πούμε σε άλλο thread.