Προγραμματισμός

Πώς να επιταχύνετε τον κωδικό σας χρησιμοποιώντας προσωρινές μνήμες CPU

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

Πώς λειτουργούν οι προσωρινές μνήμες της CPU

Οι σύγχρονες CPU έχουν συνήθως τρία επίπεδα προσωρινής μνήμης, με την ένδειξη L1, L2 και L3, η οποία αντικατοπτρίζει τη σειρά με την οποία η CPU τους ελέγχει. Οι CPU έχουν συχνά μια προσωρινή μνήμη δεδομένων, μια προσωρινή μνήμη εντολών (για κωδικό) και μια ενοποιημένη προσωρινή μνήμη (για οτιδήποτε). Η πρόσβαση σε αυτές τις κρυφές μνήμες είναι πολύ πιο γρήγορη από την πρόσβαση στη μνήμη RAM: Συνήθως, η προσωρινή μνήμη L1 είναι περίπου 100 φορές ταχύτερη από τη μνήμη RAM για πρόσβαση σε δεδομένα και η προσωρινή μνήμη L2 είναι 25 φορές πιο γρήγορη από τη μνήμη RAM για πρόσβαση σε δεδομένα.

Όταν το λογισμικό σας εκτελείται και χρειάζεται να τραβήξετε δεδομένα ή οδηγίες, οι προσωρινές μνήμες της CPU ελέγχονται πρώτα, στη συνέχεια η πιο αργή μνήμη RAM του συστήματος και τέλος οι πολύ πιο αργές μονάδες δίσκου. Αυτός είναι ο λόγος για τον οποίο θέλετε να βελτιστοποιήσετε τον κώδικά σας για να αναζητήσετε πρώτα τι είναι πιθανό να χρειαστεί από την προσωρινή μνήμη CPU.

Ο κωδικός σας δεν μπορεί να καθορίσει πού βρίσκονται οι οδηγίες δεδομένων και τα δεδομένα - το υλικό του υπολογιστή το κάνει αυτό - επομένως δεν μπορείτε να αναγκάσετε ορισμένα στοιχεία στην προσωρινή μνήμη της CPU Ωστόσο, μπορείτε να βελτιστοποιήσετε τον κωδικό σας για να ανακτήσετε το μέγεθος της προσωρινής μνήμης L1, L2 ή L3 στο σύστημά σας χρησιμοποιώντας τα Windows Management Instrumentation (WMI) για να βελτιστοποιήσετε όταν η εφαρμογή σας έχει πρόσβαση στην προσωρινή μνήμη και συνεπώς την απόδοσή της.

Οι CPU δεν έχουν ποτέ πρόσβαση στο byte cache byte. Αντ 'αυτού, διαβάζουν τη μνήμη σε γραμμές cache, οι οποίες είναι κομμάτια μνήμης γενικά σε μέγεθος 32, 64 ή 128 byte.

Η ακόλουθη λίστα κωδικών δείχνει πώς μπορείτε να ανακτήσετε το μέγεθος της προσωρινής μνήμης CPU L2 ή L3 στο σύστημά σας:

δημόσιο στατικό uint GetCPUCacheSize (string cacheType) {try {using (ManagementObject managementObject = new ManagementObject ("Win32_Processor.DeviceID = 'CPU0'")) {return (uint) (managementObject [cacheType]); }} πιάστε {return 0; }} στατικό κενό Κεντρικό (string [] args) {uint L2CacheSize = GetCPUCacheSize ("L2CacheSize"); uint L3CacheSize = GetCPUCacheSize ("L3CacheSize"); Console.WriteLine ("L2CacheSize:" + L2CacheSize.ToString ()); Console.WriteLine ("L3CacheSize:" + L3CacheSize.ToString ()); Κονσόλα. Διαβάστε (); }

Η Microsoft διαθέτει πρόσθετη τεκμηρίωση για την κλάση W32 του Win32_Processor.

Προγραμματισμός για απόδοση: Παράδειγμα κώδικα

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

Οι κρυφές μνήμες λειτουργούν καλύτερα εάν χρησιμοποιείτε μια διαδοχική δομή δεδομένων, όπως έναν πίνακα. Η διαδοχική παραγγελία επιτρέπει στην CPU να μπορεί να διαβάζει μπροστά και επίσης να διαβάζει μπροστά κερδοσκοπικά εν αναμονή του τι πιθανώς θα ζητηθεί στη συνέχεια. Έτσι, ένας αλγόριθμος που έχει πρόσβαση στη μνήμη διαδοχικά είναι πάντα γρήγορος.

Εάν έχετε πρόσβαση στη μνήμη με τυχαία σειρά, η CPU χρειάζεται νέες γραμμές προσωρινής μνήμης κάθε φορά που αποκτάτε πρόσβαση στη μνήμη. Αυτό μειώνει την απόδοση.

Το ακόλουθο απόσπασμα κώδικα εφαρμόζει ένα απλό πρόγραμμα που απεικονίζει τα οφέλη από τη χρήση δομής σε μια τάξη:

 δομή RectangleStruct {public int εύρος; δημόσιο ύψος int? } τάξη RectangleClass {public int εύρος; δημόσιο ύψος int? }

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

static void Main (string [] args) {const int μέγεθος = 1000000; var structs = νέο RectangleStruct [μέγεθος]; var class = νέο RectangleClass [μέγεθος]; var sw = νέο χρονόμετρο (); sw. Έναρξη (); για (var i = 0; i <size; ++ i) {structs [i] = new RectangleStruct (); structs [i] .breadth = 0 structs [i]. ύψος = 0; } var structTime = sw.ElapsedMilliseconds; sw. Επαναφορά (); sw. Έναρξη (); για (var i = 0; i <size; ++ i) {class [i] = new RectangleClass (); τάξεις [i] .breadth = 0; τάξεις [i]. ύψος = 0; } var classTime = sw.ElapsedMilliseconds; sw. Διακοπή (); Console.WriteLine ("Χρόνος ανά σειρά κατηγοριών:" + classTime.ToString () + "milliseconds."); Console.WriteLine ("Χρόνος ανά σειρά δομών:" + structTime.ToString () + "χιλιοστά του δευτερολέπτου."); Κονσόλα. Διαβάστε (); }

Το πρόγραμμα είναι απλό: Δημιουργεί 1 εκατομμύριο αντικείμενα δομών και τα αποθηκεύει σε μια σειρά. Δημιουργεί επίσης 1 εκατομμύριο αντικείμενα μιας τάξης και τα αποθηκεύει σε έναν άλλο πίνακα. Το πλάτος και το ύψος των ιδιοτήτων αντιστοιχούν σε τιμή μηδέν σε κάθε παρουσία.

Όπως μπορείτε να δείτε, η χρήση δομών φιλικών προς την προσωρινή μνήμη παρέχει τεράστιο κέρδος απόδοσης.

Κανόνες για καλύτερη χρήση της προσωρινής μνήμης CPU

Λοιπόν, πώς γράφετε κώδικα που χρησιμοποιεί καλύτερα την προσωρινή μνήμη της CPU; Δυστυχώς, δεν υπάρχει μαγικός τύπος. Υπάρχουν όμως μερικοί κανόνες:

  • Αποφύγετε τη χρήση αλγορίθμων και δομών δεδομένων που εμφανίζουν ακανόνιστα μοτίβα πρόσβασης στη μνήμη. Χρησιμοποιήστε αντ 'αυτού γραμμικές δομές δεδομένων.
  • Χρησιμοποιήστε μικρότερους τύπους δεδομένων και οργανώστε τα δεδομένα, ώστε να μην υπάρχουν τρύπες ευθυγράμμισης.
  • Εξετάστε τα μοτίβα πρόσβασης και εκμεταλλευτείτε τις γραμμικές δομές δεδομένων.
  • Βελτιώστε τη χωρική τοποθεσία, η οποία χρησιμοποιεί κάθε γραμμή προσωρινής μνήμης στο μέγιστο βαθμό μόλις αντιστοιχιστεί σε προσωρινή μνήμη.