Raspberry Fields Forever

Un peu d'Admin ,Un zeste de DEV
28 décembre 2016

Depuis sa sortie, je suis en admiration devant les raspberry Pi, ça sert à tout, c’est pas très cher et linux fonctionne dessus.
Dans des temps anciens, j’ai étudié le calcul parallèle , notamment MPI et PVM. C’était marrant, mais je n’en ai pas fait mon métié.
En fouillant un peu l’internet, j’ai vu qu’il était relativement simple de monter des raspberry en cluster, d’ou l’idée de faire le mien: un petit cluster Pi pédagogique.

Le Hardware

Pour se faire, Amazon est ton ami:
les bestiolles: https://www.amazon.fr/gp/product/B01CCOXV34/ , j’en ai pris 6
Le ‘mini’ rack: https://www.amazon.fr/gp/product/B01COU8Z1O/
L’alimentation: https://www.amazon.fr/gp/product/B00YTJ45HM/
Les cables d’alimentation: https://www.amazon.fr/gp/product/B00OOOHPN8/
Le switch: https://www.amazon.fr/gp/product/B00A33BYRC/
Les RJ45 de 30 cm: https://www.amazon.fr/gp/product/B00DCWFZO4/
Les MicroSD: https://www.amazon.fr/gp/product/B0162YQG2I/


Le Software
Le système d’exploitation

Sans surprise une raspbian. J’ai fais une seule installation propre:

  1. Serveur SSH
  2. Montage NFS sur un synology pour les datas communes
    192.168.1.7:/volume1/nfscpi /usr/local nfs defaults 0 0

Activation du service rpcbin pour nfs

systemctl enable rpcbind

Editer le fichier /etc/hosts ou utilisé votre dns privé.

127.0.0.1    localhost
::1     localhost ip6-localhost ip6-loopback
ff02::1     ip6-allnodes
ff02::2     ip6-allrouters
192.168.1.50    cpi1.andytoys.fr cpi1
192.168.1.51    cpi2.andytoys.fr cpi2
192.168.1.52    cpi3.andytoys.fr cpi3
192.168.1.53    cpi4.andytoys.fr cpi4
192.168.1.54    cpi5.andytoys.fr cpi5
192.168.1.55    cpi6.andytoys.fr cpi6
127.0.1.1   raspberrypi

Puis j’ai mounté ma carte sd sur mon pc de bureau:

dd if=/dev/sdi of=image_cpi bs=2048

et cloné l’image sur chaque carte sd:

dd if=image_cpi of=/dev/sdi bs=2048

Ensuite, il suffit de changer la conf (ip, nom réseau, etc …) spécifique à chaque noeud.

Manager le tout

Pour faire des installations en parallèle sur les nœuds du cluster PI, j’ai utilisé clusterssh sur mon poste de travail.

apt install clusterssh

Il fait une copie de ce que l’utilisateur tape au clavier sur tous les nœuds.

Depuis la machine ou cssh est lancé, il faut copié votre clé publique ssh sur tous les noeuds et créer le fichier /etc/clusters

 clusterpi cpi1 cpi2 cpi3 cpi4 cpi5 cpi6 

Et lancer

cssh user@clusterpi
MPI

Via cssh:

apt install mpi-default-dev
apt install mpi-default-bin

Sur un des nœuds:
J’ai récupéré un fichier example du calcul de pi :cpi.c sur le site de MPI.

/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
 *  (C) 2001 by Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */

#include "mpi.h"
#include <stdio.h>
#include <math.h>

double f(double);

double f(double a)
{
    return (4.0 / (1.0 + a*a));
}

int main(int argc,char *argv[])
{
    int    n, myid, numprocs, i;
    double PI25DT = 3.141592653589793238462643;
    double mypi, pi, h, sum, x;
    double startwtime = 0.0, endwtime;
    int    namelen;
    char   processor_name[MPI_MAX_PROCESSOR_NAME];

    MPI_Init(&argc,&argv);
    MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD,&myid);
    MPI_Get_processor_name(processor_name,&namelen);

    fprintf(stdout,"Process %d of %d is on %s\n",
        myid, numprocs, processor_name);
    fflush(stdout);

    n = 2000000000;         /* default # of rectangles */
    if (myid == 0)
    startwtime = MPI_Wtime();

    MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

    h   = 1.0 / (double) n;
    sum = 0.0;
    /* A slightly better approach starts from large i and works back */
    for (i = myid + 1; i <= n; i += numprocs)
    {
    x = h * ((double)i - 0.5);
    sum += f(x);
    }
    mypi = h * sum;

    MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

    if (myid == 0) {
    endwtime = MPI_Wtime();
        printf("pi is approximately %.16f, Error is %.16f\n",
           pi, fabs(pi - PI25DT));
    printf("wall clock time = %f\n", endwtime-startwtime);           
    fflush(stdout);
    }

MPI_Finalize();
return 0;
}

J’ai fixé n = 2000000000
Créé un fichier ~/machine qui contient le nom de vos noeuds:

cpi1
cpi2
cpi3
cpi4
cpi5
cpi6

Compilation:

mpicc -g -O3 cpi.c  -o /usr/local/cpi  -lm

Execution:

mpiexec -machinefile machine  -n <nombre de process>  /usr/local/cpi
Les resultats

Raspberry Pi:

model name   : ARMv7 Processor rev 4 (v7l)
BogoMIPS    : 38.40

Sur 1 noeud à 4 coeurs:

mpiexec   -n 4 /usr/local/cpi
pi is approximately 3.1415926535898393, Error is 0.0000000000000462
wall clock time = 37.888490

Sur l’ensemble du cluster 6*4 coeurs:

 mpiexec -machinefile machine  -n 24 /usr/local/cpi
 pi is approximately 3.1415926535898175, Error is 0.0000000000000244
 wall clock time = 6.369657

ça a le mérite de fonctionner, niveau perf c’est pas top ! vu la puissance d’un raspberry PI.
A titre indicatif, sur mon pc de bureau:

model name   : Intel(R) Core(TM) i5-3350P CPU @ 3.10GHz
stepping    : 9
cpu MHz     : 3112.109
cache size  : 6144 KB
bogomips    : 6186.28


mpiexec -n 4 ./cpi
pi is approximately 3.1415926535898393, Error is 0.0000000000000462
wall clock time = 2.342589

C’était juste pour m’amuser un peu.
Joyeuses fêtes à tous.