mercredi 1 février 2017

Network Boot Raspberry Pi2

Voici un très court résumé de ce que nous allons devoir faire pour faire booter un Raspberry Pi 2 (RPi2) via le réseaux.

  1. sdcard + bootcode.ini
  2. DHCP/BOOTP
  3. TFTP
  4. NFSv2 (voir ce post)
  5. Brancher

Prérequis : Vous devez avoir un serveur DHCP configurable sur votre réseau.
Attention : Le serveur DHCP intégré dans les box des opérateurs internet n’est en général pas suffisamment configurable. 


1) Télécharger bootbin.bin  ici : https://github.com/raspberrypi/firmware/tree/master/boot
Mettre ce fichier sur une  carte micro SD vierge formatée en FAT32.
Mettre cette carte dans le RPi 2. (ne pas mettre en marche)


2) Configurer le serveur DHCP. Ici je donne la configuration du DHCP sur un switch Cisco.
A vous d'adapter à vos adresses ip.

ip dhcp excluded-address 192.168.0.1 192.168.0.100

ip dhcp pool CLUSTER
   network 192.168.0.64 255.255.255.192
   dns-server 8.8.8.8 
   option 43 ascii "Raspberry Pi Boot   "
   default-router 192.168.0.100 
   option 66 ascii 192.168.0.70

IMPORTANT : Il y a 3 espaces après Boot à la fin de "Raspberry Pi Boot   "

- network définit le (sous)réseaux dans lequel  les adresse ip sont allouées par le serveur dhcp.
Le « ip dhcp excluded-address exclue les ip  de 1 à 100. L’allocation aura donc lieu dans l’intervalle 101..126
- dns-server définit l’ip du résolveur dns. Ici celui de Google.
- default-router définit l'ip de la gateway (routeur)
- option 66 définit le nom du serveur TFTP, donné sous forme d’adresse IP.


3) Configuration du serveur TFTP  (ici configuration avec Centos 7)

yum install tftp-server tftp
systemctl start tftp 
systemctl enable tftp

Mettre tous les fichiers nécessaires au boot d’un RPi2 (ou d’un RPi3) dans la racine du serveur TFTP.
Par défaut le serveur TFTP sert  les fichiers qui sont dans /var/lib/tftpboot

Télécharger les dernière versions depuis  https://github.com/raspberrypi/firmware/tree/master/boot
ou prendre des version plus 'mature' sur la partition FAST d'une sdcarte carte. Cette partition est ensuite montée sous le nom de /boot.


bootcode.bin
On l’a déjà mis sur la carte de notre Rpi2, mais un Rpi3 sans sdcard peut le prendre directement sur le serveur TFTP.

Les 4 fichiers start*.elf
Celui utilisé dépendra de la répartition mémoire entre GPU et CPU
(Voir paramètre gpu_mem=... dans config.txt)
    start.elf
    start_cd.elf
    start_x.elf
    start_db.elf 

A chaque fichiers start*.elf correspond un fichier fixup*.dat
    fixup.dat  
    fixup_cd.dat 
    fixup_x.dat
    fixup_db.dat  

Le kernel ARM7 32 bits multi cores commun à RPi2 et RPi3
    kernel7.img

Les Device Tree
    bcm2709-rpi-2-b.dtb
    bcm2710-rpi-3-b.dtb

Créer les deux fichiers de configuration vide (on les remplira plus tard)
    config.txt
    cmdline.txt


4) Enfin, mettre le RPi sous tension.
Dans /var/log/message on doit trouver l’activité du serveur TFTP
   tftpd: Client 192.168.0.126 finished config.txt
   tftpd: Client 192.168.0.126 finished start.elf
   tftpd: Client 192.168.0.126 finished fixup.dat
   tftpd: Client 192.168.0.126 finished config.txt
   tftpd: Client 192.168.0.126 finished config.txt
   tftpd: Client 192.168.0.126 finished cmdline.txt
   tftpd: Client 192.168.0.126 finished kernel7.img
   tftpd: Client 192.168.0.126 finished bcm2709-rpi-2-b.dtb
   tftpd: Client 192.168.0.126 finished config.txt

Note: Le serveur TFTP ne montre que les transferts effectifs. Si on regarde avec tcpdump le trafic réseaux on découvre que le processus de boot teste l’existence de bien d'autres fichiers:

tcpdump -l -n -v -ttttt -i eth0 -s 1500 udp  | grep –line-buffered RRQ | awk ‘{print $6}’


   358bec05/start.elf 
   autoboot.txt 
   config.txt 
   recovery.elf 
   start.elf 
   fixup.dat 
   recovery.elf 
   config.txt 
   dt-blob.bin 
   recovery.elf 
   config.txt 
   bootcfg.txt 
   cmdline.txt 
   recovery7.img 
   recovery.img 
   kernel7.img 
   armstub7.bin 
   armstub.bin 
   kernel7.img 
   bcm2709-rpi-2-b.dtb 
   config.txt

Cette séquence varie en fonction des fichiers effectivement trouvés sur le serveur TFTP et en fonction du contenu de config.txt

Si tout se passe bien vous aurez au bout d'environ 5 ou 6 secondes la mire colorée, puis les info du chargement du kernel qui se terminera pas un message du type:

PANIC Unable to mount root fs. 

C'est normal ! L’étape suivante est de justement fournir ce root file system via NFSv2.

Si rien ne ce passe il faudra debugger le DHCP puis le TFTP avec tcpdump ou wireshark.
Pour voir tout le trafic il faudra utiliser un hub, pas un switch.
Quand le processus de boot échoue le led d’activité clignote 4 fois (parfois 7).
Si le RPi2 émet plusieurs requêtes DHCP alors que le serveur DHCP lui répond c'est que la réponse ne lui convient pas.


lundi 20 juin 2016

Créer une SD carte master pour RPi

Voici comment dupliquer 'intelligemment' une carte mémoire d'un Raspberry pi.
L'image de la certe peut ensuite etre archivé, et etre utiliser comme 'master'.

'Intelligemment' veut dire que l'on ne va pas dupliquer tout le support physique si ce n'est pas nécessaire.

Étape 1 : Évaluer la taille utile sur la carte micro SD

Depuis le RPi que le font dupliquer taper :

# fdisk  -l

Disk /dev/mmcblk0: 15.9 GB, 15931539456 bytes, 31116288 sectors
        Device Boot  Start     End  Blocks   Id  System

/dev/mmcblk0p1        2048  616447  307200    c  W95 FAT32 (LBA)
/dev/mmcblk0p2      616448 1665023  524288   82  Linux swap
/dev/mmcblk0p3     1665024 5859327 2097152   83  Linux

On voit que le support physique (/dev/mmcblk0) fait 31116288 secteurs (donc ~ 14.8 Go)  alors que la dernière partition (/dev/mmcblk0p3)  s’arrête au secteur 5859327 (~ 2.8 Go). Il suffit donc de faire une image des 5859328 premiers secteurs. Un secteur faisant 512 octets cela fait 2929664 ko à sauvegarder. Soit encore 183104 x 16 k.

Étape 2 : Créer le fichier image

Depuis une autre machine ayant suffisamment d’espace disque, on peut aller pomper l’image d’un des raspberry du cluster en utilisant dd au travers de ssh :

# ssh root@rbpi09 "dd if=/dev/mmcblk0 count=183104 bs=16k" > /tmp/rpi.img
183104+0 records in
183104+0 records out
2999975936 bytes copied, 328.288 s, 9.1 MB/s


Étape 3: Vérifier / retoucher l’image

La commande ‘file’ va indiquer si le fichier est reconnaissable

# file rpi.img
rpi.img: x86 boot sector;
 
partition 1: ID=0xc, starthead 32, startsector 2048, 614400 sectors;
partition 2: ID=0x82, starthead 94, startsector 616448, 1048576 sectors;
partition 3: ID=0x83, starthead 163, startsector 1665024, 4194304 sectors, code offset 0xb8

Avec la commande fdisk -l rpi.img on retrouve les même info.

On peut monter les partitions fat32 et Linux, à condition de donner leur offset de début dans le fichier à l’octet prêt, c’est-à-dire offset = 512  * Secteur de démarrage.
Pour la partition FAT32 offset = 512 * 2048 = 10315776
Pour la partition Linux  offset = 512 * 1665024 = 852492288

 # mkdir /mount/img
 # mount -o loop,offset=852492288 rpi314.img2 /mnt/img
On peut même aller modifier les fichiers dans /mnt/img (pour vider des log par exemple)
On termine par : umount /mnt/img

Si on veut manipuler les partitions (changement de taille, tester le file system) on ne peut pas le faire si le fichier image est montée avec 'mount'. Il faut à la place créer une interface loopback avec la commande 'losetup' :

 # losetup -o offset -f --show rpi.img 

remplacer offset par l'offset de début de la partition (comme avec mount)
Grace à l'option --show losetup affiche sur quelle interface la partition a été montée. (En général /dev/loop1)

On peut alors utiliser cette interface comme on le fait
# fsk /dev/loop1
e2fsck 1.42.9 (28-Dec-2013)
/dev/loop1: clean, 68537/131072 files, 341154/524288 blocks

Terminer avec ' losetup -D'  pour détacher toutes les interfaces loopback.
Le fichier image peut être compressé pour être archivé, ou être utilisé pour créer d'autre cartes micro SD.

Étape 5 : Graver l'image


mercredi 18 mai 2016

OpenMP vs OpenMPI vs MPICH

Dès que l’on s’intéresse à la programmation parallèle on rencontre ces trois acronymes OpenMP, Open MPI et MPICH dont les noms entretiennent la confusion
  • OpenMP = Open Multi-Processing
  • Open MPI = Open Message Passing Interface
  • MPICH = Message Passing Interface over CHameleon
Les trois fonctionnent avec C/C++ et Fortran et sont supportés  par gcc et les principaux compilateurs. Leur but commun est de permettre le développement de programmes parallèles.



OpenMP est principalement implémenté au travers d’extensions du compilateur C/C++ ou Fortran. Des directives sont données au compilateur au travers de #pragma (ou de !$ pour Fortran) afin qu’il génère des blocs  de code s’exécutant en parallèle sur des architectures multiprocesseurs à mémoire partagée. Typiquement une machine Linux ou Windows avec un i5 ou i7 ou un Raspberry Pi avec un ARM7 ou ARM8. 

L'avantage de OpenMP est d’être très peu intrusif et de rendre la parallélisation d'un programme plus naturelle. Pour apprendre OpenMP la chaine OpenMP sur YouTube est excellente!


Open MPI  et MPICH sont deux implémentations du standard  MPI (Message Passing Interface). Leur but est de produire un programme qui s’exécute en parallèle sur les ordinateurs d’un réseau. Le partage de donnée ne se fait pas via la mémoire comme avec OpenMP mais via le réseau. C’est plus lent mais plus extensible et c'est le seul moyen de faire travailler des centaines ou milliers de processeurs ensemble. Les performances et la fiabilité du réseau sont donc critiques dans les applications MPI mais

Les principaux supports de Open MPI sont Cisco, Intel, Nvidia et les principaux supports de MPICH sont Cray, IBM, Intel, Microsoft. Fin 2015 MPICH est utilisé sur 9 des 10 plus puissants ordinateurs du monde.

Tout un écosystème d’applications gravite autour de MPI. Les programmes s’exécutant sur des clusters d’ordinateurs  il faut des  logiciels pour administrer/superviser  le cluster.

Tout langage qui peut s'interfacer avec une librairie C peut utiliser MPI : Python, Perl ...

TRÈS IMPORTANT : Rien n’empêche d’utiliser OpenMP en même temps que OpenMPI ou MPICH. Par contre on n’utilise jamais ensemble OpenMPI et MPICH.

mercredi 20 avril 2016

Rasberry Pi2 vs Pi3

Faut-il remplacer les Raspberry Pi2 B de  notre cluster par des  Raspberry Pi3 ?

Voici 3 réflexions:

1) La première est que l’utilisation de 64 bits (ARMv8)  induit automatiquement l’utilisation de plus de mémoire aussi bien pour le code que les données. Le classique index de boucle
for (int i=0 ; i<1000 ; i++) { … } 
prenait 32 bits (alors que 16 suffisaient largement) maintenant il en faudra 64 sans aucun gain. Sur un serveur avec 16 Go de RAM on ne s’inquiète pas de ce genre de détail, mais sur une RPi avec seulement 1 Go (dont une partie est prise par la vidéo) on fait beaucoup plus attention. 

Notez que :
- Avec des pointeurs sur 32 bits on peut adresser 4 Go. Donc 32 bits sont largement suffisant pour un RPi.
- Si on écrit "for ( int16 i=0 …)" c’est le code qui est plus lent.
- Cette inflation des besoins en mémoire induite par le passage de 16 à 32 puis à 64 bits coûte tellement cher pour les applications embarquées qu’ARM a développé un jeu d’instructions 16 bits (Thumb et Thumb-2).


2) Le deuxième réflexion est que, pour le moment, on n’a pas de distributions Linux 64 bits (aarch64) utilisant le nouveau jeu d’instruction de ARMv8.  Or ce qui fait l’intérêt de l’architecture ARMv8 c’est que son jeu d’instructions a été conçu sans la contrainte de compatibilité avec le jeu d’instructions 32 bits. La performance ne vient pas des 64 bits mais de ce design moderne et sans compromis. (Le travail est en cours avec CentOS-7)

3) Comparaison des vitesses de calcul:

Note: Chaque RPi2 de notre cluster est légèrement over-clocké (1GHz) sans jamais avoir de plantages (mais alimenté en 5.2V) . Dans le fichier /boot/config.txt on a :

arm_freq=1000
core_freq=600
sdram_freq=500
over_voltage=2
over_voltage_sdram_p=4
over_voltage_sdram_i=0
over_voltage_sdram_c=0


Pour faire cette comparaison entre RPi2 à 1GHz et RPi3 à 1.2GHz (et avec un Intel i7) on va utiliser la commande “openssl speed rsa -multi x” où x est le nombre de threads à utiliser.
On devrait avoir un gain de 20% en faveur du RPi3.


Voici les résultats obtenue avec openssl 1.0.1


**** Résultats sur un RPi3 ****

[rpi3 ~]# openssl speed rsa -multi 1
================= RPi3 1x1.2Ghz ====================
                  sign    verify    sign/s  verify/s
rsa  512 bits 0.000775s 0.000067s   1290.0   15000.4
rsa 1024 bits 0.003928s 0.000198s    254.6    5038.5
rsa 2048 bits 0.024988s 0.000704s     40.0    1419.6
rsa 4096 bits 0.172203s 0.002684s      5.8     372.6


[rpi3 ~]# openssl speed rsa -multi 4
================= RPi3 4x1.2Ghz ====================
                  sign    verify    sign/s  verify/s
rsa  512 bits 0.000195s 0.000019s   5115.2   53333.3
rsa 1024 bits 0.001344s 0.000073s    744.3   13746.1
rsa 2048 bits 0.009693s 0.000283s    103.2    3535.3
rsa 4096 bits 0.071341s 0.001157s     14.0     864.3



**** Résultats sur un des RPi2 du cluster ****

[rpi2 ~]# openssl speed rsa -multi 1
================= RPi2 1x1Ghz ======================
                  sign    verify    sign/s  verify/s
rsa  512 bits 0.001373s 0.000109s    741.4    9259.0
rsa 1024 bits 0.006555s 0.000340s    152.5    2940.4
rsa 2048 bits 0.043712s 0.001256s     22.9     797.4
rsa 4096 bits 0.312812s 0.004840s      3.2     206.6


[rpi2 ~]# openssl speed rsa -multi 4
================= RPi2 4x1Ghz ======================
                  sign    verify    sign/s  verify/s
rsa  512 bits 0.000342s 0.000027s   2923.9   36613.4
rsa 1024 bits 0.001644s 0.000085s    608.1   11721.2
rsa 2048 bits 0.010966s 0.000315s     91.2    3179.8
rsa 4096 bits 0.078496s 0.001213s     12.7     824.4



On constate que le RPi3 apporte bien un gain de vitesse souvent de plus de 20% sur le calcul pur. Donc avec un Linux 32 bits (ARMv7) on a l'avantage de la vitesse sans avoir besoin de plus de mémoire. Il n'est donc pas sur qu'un linux 64 bits (ARMv8) soir vraiment utile. 
Le gain en calcul pur est malheureusement noyé dans le fait que tout le reste est à la même vitesse sur un RPi2 et RPi3. On aurait plus besoin de 2 Go de RAM et d'un port Giga Ethernet. (Comme sur le ODROID-C2). 

Donc, si on devait faire un upgrade ce serait plus pour un odroid-c2 qu'un RPi3 !


**** Résultats sur un intel i7 3.1Ghz ****

[i7 ~]# openssl speed rsa -multi 1
================= i7-4770S 1x3.1Ghz ================
                  sign    verify    sign/s  verify/s
rsa  512 bits 0.000041s 0.000003s  24187.4  297005.8
rsa 1024 bits 0.000162s 0.000009s   6158.7  114694.3
rsa 2048 bits 0.000980s 0.000029s   1020.9   34625.3
rsa 4096 bits 0.007335s 0.000108s    136.3    9241.4



[i7 ~]# openssl speed rsa -multi 4
================= i7-4770S 4x3.1Ghz ================
                  sign    verify    sign/s  verify/s
rsa  512 bits 0.000012s 0.000001s  86956.5 1000000.0
rsa 1024 bits 0.000046s 0.000003s  21831.1  400000.0
rsa 2048 bits 0.000273s 0.000008s   3659.7  120320.9
rsa 4096 bits 0.002098s 0.000032s    476.6   31564.4



[i7 ~]# openssl speed rsa -multi 8
================= i7-4770S 8x3.1Ghz ================
                  sign    verify    sign/s  verify/s
rsa  512 bits 0.000011s 0.000001s  93570.5 1089285.7
rsa 1024 bits 0.000047s 0.000003s  21498.2  400000.0
rsa 2048 bits 0.000276s 0.000008s   3617.7  125000.0
rsa 4096 bits 0.002074s 0.000030s    482.1   33773.2


Pour voir la fréquence d'horloge en temps réel:
cat /sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_cur_freq


Benchmarks officiels: https://www.raspberrypi.org/magpi/raspberry-pi-3-specs-benchmarks/