Αποφάσισα χτες να κάνω μια σοβαρότερη προσπάθεια όσον αφορά στα interrupts και τον επιμερισμό των processes.
Στα τελευταία images /usr/bin/archphile-optimize υπήρχαν τα παρακάτω sections:
Code:
# IRQ affinity optimization - Do not apply it if you are using Raspberry Pi 2 !!!
#/usr/bin/irq-archphile
# set affinity of MPD in one core - choose values from 0-3
#taskset -c -p 2 $(pidof mpd)
Στην περίπτωση που κάποιος ενεργοποιούσε το /usr/bin/irq-archphile, αυτό αντιστοιχούσε στην εκτέλεση του παρακάτω script (είναι διαφορετικό για κάθε συσκευή - το παρόν script αφορά στο odroid c2)
Code:
#!/bin/bash
# Cores 1 2 3 4 have to be put as 1 2 4 8
# USB bus
echo "8" > /proc/irq/62/smp_affinity
echo "8" > /proc/irq/63/smp_affinity
# Ethernet
echo "2" > /proc/irq/40/smp_affinity
Το script αυτό κάνει επί της ουσίας ανακατανομή των hardware interrupts σε διάφορα cores. Αυτό κανονικά θα έπρεπε να γίνεται από το ίδιο το OS. Παρόλα αυτά, μια συνηθισμένη κατάσταση σε ARM boards, είναι όλα τα interrupts να πέφτουν αποκλειστικά στο πρώτο core, εκτός από συγκεκριμένα που πρέπει για συστημικούς λόγους να πέφτουν σε όλα. Έτσι εγώ αποφάσισα να ρίχνω τα interrupts 62 και 63 (USB Bus) στο 4ο core και 40 (ethernet) στο 2ο core.
Στη συνέχεια με την εντολή taskset, όριζα στον MPD να χρησιμοποιεί αποκλειστικά τo 3o core.
Η κατάσταση ήταν καλύτερη από την default, αλλά όχι εντελώς φροντισμένη. Έτσι χτες έκανα το εξής:
- Με τη χρήση ενός kernel parameter με ονομασία isolcpus, απάιτησα από το OS να μην προορίζει κανένα process στο core που παίζει ο MPD. Αυτό το έκανα με την προσθήκη του:
στο /boot/boot.ini
στο section
setenv bootargs.
Λαμβάνοντας υπόψιν ότι τα cores είναι 0,1,2,3, η παραπάνω εντολή, αφήνει στην ησυχία του το 3o core το οποίο πλέον θα χρησιμοποιηθεί μόνο από processes που θα του ρίξουμε εμείς με την taskset. Έτσι με αυτή την προσθήκη και με το
Code:
taskset -c -p 2 $(pidof mpd)
O MPD όχι μόνο τρέχει σε ένα συγκεκριμένο core, αλλά είναι αποκλειστικά δικό του, με εξαίρεση συγκεκριμένα interrupts τα οποία είναι αδύνατον να αποκλειστούν από το core αυτό.
Στην περίπτωση του odroid C2, το 3ο core χρησιμοποιείται πλέον μόνο για τον MPD, και για τα interupts του meson-timer.
Συνοψίζοντας μέχρι τώρα, είχα καταφέρει τα εξής:
- Διάφορα hardware interrupts να πέφτουν στο 1o core,
- Τα σημαντικότερα για μια δικτυακή audio εφαρμογή interupts να διαμοιράζονται σε ξεχωριστά cores (2o και 4ο)
- O MPD να παίζει μπάλα μόνος του στο 3ο
Κάπου εδώ αποφάσισα να το τραβήξω από τα μαλλιά. Είχα φροντίσει τα πάντα, εκτός από όλα τα υπόλιπα processes του συστήματός μου. Αφού τσέκαρα με το taskset σε ποια CPUS πεφτουν και πήρα για όλα (εκτός του MPD) την απάντηση, ότι συστημικά μπορούν να πέσουν στα 0,1,3 (επιβεβαιώνοντας έτσι ότι όντως είχα αποκλείσει το 3o core με αριθμό 2 υπενθυμίζω), ξεκίνησα να ρίχνω ένα ένα τα processes στο 1o core. Έτσι αυτή τη στιγμή, η λίστα με τα tasksets είναι αυτή:
Code:
taskset -c -p 2 $(pidof mpd)
taskset -c -p 0 $(pidof ympd)
taskset -c -p 0 $(pidof rngd)
taskset -c -p 0 $(pidof systemd-journald)
taskset -c -p 0 $(pidof systemd-logind)
taskset -c -p 0 $(pidof systemd-udevd)
taskset -c -p 0 $(pidof dbus-daemon)
taskset -c -p 0 $(pidof init)
taskset -c -p 0 $(pidof lircd)
Δεν είναι όλα ακόμα στη λίστα αυτή. Απουσιάζουν τα avahi, devmon, upmpdcli, shairport κλπ που εγώ δε χρησιμοποιώ ποτέ, αλλά θα ασχοληθώ με αυτά, καθώς και κάποια άλλα, όπως agetty πχ, που δεν έχω καταφέρει ακόμα να τα πειράξω.
Έτσι πλέον η κατάσταση είναι η εξής:
- 1o core --> έχει όλη τη "σαβούρα"
- 2ο core --> ασχολείται με τα interupts του ethernet
- 3o core --> ασχολείται μόνο με τον MPD
- 4o core --> ασχολείται μόνο με τα interrupts του USB bus
Είναι νομίζω η πρώτη φορά που βλέπω σωστά κατανεμημένη χρήση CPU στο σύστημά μου.
Να σημειωθεί ότι όλα τα παραπάνω, αν τα πειράξουμε πολύ σε ένα OS, υπάρχει περίπτωση να τα κάνουμε χειρότερα, καθώς συνήθως ο scheduler ξέρει να κάνει τη δουλειά καλύτερα από μας. Οι λόγοι που έκανα όλες αυτές τις αλλαγές ήταν:
- είχα παρατηρήσει ότι σχεδόν όλα τα interrupts έπεφταν στο 1o core
- γενικά τα υπόλοιπα 3 δεν έκαναν και πολλά πράγματα
- είχα ζήσει με το συνδυασμό Archphile + παλιό μονοπήρυνο RPI, το οποίο σε ένα CPU του κώλου έπαιζε τα πάντα χωρίς να "μασάει", όπότε ήξερα ότι όσο και να πιέσω το 1ο core με τη σαβούρα που θα του ρίξω δεν πρόκειται να δημιουργήσω κανένα θέμα.
Σε ένα σύστημα με περισσότερα και πιο απαιτητικά processes, όλα τα παραπάνω θα ήταν μια πολύ πιο δύσκολη υπόθεση.
Τέλος παραθέτω μερικά ενδιαφέροντα links:
https://access.redhat.com/documenta.../html/Performance_Tuning_Guide/s-cpu-irq.html
https://access.redhat.com/documenta...tem_Tuning-Interrupt_and_Process_Binding.html
http://xmodulo.com/run-program-process-specific-cpu-cores-linux.html
Ειδικά για το RPI:
https://www.raspberrypi.org/forums/viewtopic.php?f=66&t=100714
Hardware IRQ affinity isn't possible due to the way that the interrupt controller has been implemented.
Because the entirety of the hardware apart from the A7s is untouched, the BCM2835 interrupt routing is still in place. This exposes two lines (nIRQ and nFIQ) that go into the A7 interrupt routing. There is no vectored interrupt controller implemented for the A7s - a simple register-based interface is used to route the global top-level interrupt to a specific core, therefore a single core will get all interrupts and have to service them.