mercoledì 24 novembre 2021

Tensorflow su Apple M1 Metal

Ho provato Tensorflow su M1 ed ha una velocita' imbarazzante...ci sono ancora alcuni problemi da risolvere ma la velocita' di M1 e' comparabile se non migliore delle GPU NVidia

Per installarlo si puo' usare le istruzioni a questo link

python3 -m venv ~/tensorflow-metal 
source ~/tensorflow-metal/bin/activate 
python -m pip install -U pip
chmod +x ~/Downloads/Miniforge3-MacOSX-arm64.sh sh
~/Downloads/Miniforge3-MacOSX-arm64.sh 
source ~/miniforge3/bin/activate
conda install -c apple tensorflow-deps
conda install -c apple tensorflow-deps==2.5.0
python -m pip install tensorflow-macos
python -m pip install tensorflow-metal

(ho installato la 2.5.0 per problemi con la 2.6 su reti che gia' usavo su altre macchine)



Per confronto lo stesso addestramento di rete neurale eseguito su M1 ha impiegato 109 secondi. Su una NVidia Quadro K620M (tensorflow-gpu dockerizzato su Linux) ha impiegato 346 secondi. Su un I7-5500 4 core il medesimo calcolo ha impiegato 1684 secondi 

martedì 23 novembre 2021

Foraminifera tensorflow retraining inception

 Un tentativo con risultati migliori di effettuare il riconoscimento di foraminiferi mediante rete neurale

Stavolta ho usato il retraining di Inception V3 usando le immagini che possono essere scaricate da qui (fonte http://endlessforams.org/)

Si tratta di 24 specie con foto a risoluzione di 1 pixel/micron




in totale il dataset e' formato da 3685 immagini di cui 80% di training e 20% di validazione


Il notebook puo' essere visualizzato su Github all'indirizzo


Il valore di batch ottimale e' compreso tra 32 e 40 per valori superiori non ci sono significativi miglioramenti...al di sotto degrada rapidamente




Come si osserva il modello performa quasi perfettamente sul training dataset (dato non interessante) mentre ha un riconoscimento compreso tra un minimo dell'80% ad un massimo del 90% sul dataset di validazione con un netto miglioramento delle prove precedenti







giovedì 18 novembre 2021

Mandelbrot Cuda su Nvidia Jetson Nano

Ho ripreso in mano la scheda Jetson Nano per iniziare a programmare in CUDA 

Gli esempi di CUDA hanno gia' un sorgente per l'insieme di Mandelbrot ma visto che era a scopo didattico sono partito da zero


L'idea e' quella di usare la GPU per i calcoli. Ogni thread calcola una riga dell'immagine. Visto che ogni block della Nvidia puo' gestire al massimo 1024 thread la massima dimensione che il sorgente puo' generare e' 1024x1024

Per condividere una memoria tra la GPU e la CPU (ognuna puo' accere solo alle proprie risorse) si usa  cudaMallocManaged. CudaMemset port i valori della matrice tutti a zero


la funzione kernel e'e quella che viene eseguita dalla GPU. Una volta lanciato il kernel la GPU restituisce il controllo alla CPU solo quando tutti i threads sono terminati. La variabile threadIdx viene utilizzate come indice di colonna dell'immagine

al termine l'array viene convertito in una immagine ppm a scala di grigio (nello specifico si sono solo due colori)

per compilare si usa nvcc con gli switch per indicano la compilazione sull'architettura 50 (relativa alla GPU sulla Jetson) con l'ottimizzazione fast_math

nvcc -use_fast_math -arch=sm_50 mand.cu -o mand

Ho usato VSCode con il terminale ma per programmare Cuda si puo' usare NSight (una versione di Eclipse con plugin NVidia) contenuto nei Cuda Tools

questo il codice

#include <stdio.h>
#include <time.h>

__global__ void kernel (int max, char *matrice)

{
int id = threadIdx.x;

/*zoom1
const double CxMin=-0.3041;
const double CxMax=-0.1874;
const double CyMin=-0.8867;
const double CyMax=-0.7699;*/

/*zoom2*/
const double CxMin=-0.2;
const double CxMax=-0.074;
const double CyMin=-1.058;
const double CyMax=-0.933;

/*insieme completo
const double CxMin=-2.5;
const double CxMax=1.5;
const double CyMin=-2.0;
const double CyMax=2.0;*/
const int iterazioni = 4096;
double x_new,y_new,x,y;
double a,b;

double PixelWidth=(CxMax-CxMin)/max;
double PixelHeight=(CyMax-CyMin)/max;

for (int s=0;s<max;s++)
{
x = 0;
y = 0;
a = CxMin + (PixelWidth*id);
b = CyMin + (PixelHeight*s);
for (int k=0;k<iterazioni;k++)
{
x_new = (x*x)-(y*y)+a;
y_new = (2*x*y)+b;
if (((x_new*x_new)+(y_new*y_new))>4)
{
// colora il punto
matrice[id*max+s] =(k%2)*255;
k=iterazioni;
}
x = x_new;
y = y_new;
}
}
}

int main(void)
{

clock_t tic = clock();
// crea la matrice in GPU
int dimensione = 1000;
char *matcuda;
// crea un array Cuda
cudaMallocManaged(&matcuda,dimensione*dimensione*sizeof(char));
// azzera tutti i valori dell'array
cudaMemset(matcuda,0,dimensione*dimensione*sizeof(char));

// 1024 e' il numero di threads che vengono eseguiti in contemporanea
// e' il valore massimo per ogni block della NVidia
// tra parentesi si possono passare variabili al kernel
kernel <<<1, dimensione>>>(dimensione,matcuda);
cudaDeviceSynchronize();
clock_t toc = clock();
/*
for (int s=0;s<dimensione;s++)
{
for (int t=0;t<dimensione;t++)
{
printf("%i",matcuda[(dimensione*s)+t]);
}
printf("\n");
}
*/
printf("Elapsed: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC);

FILE *fpi = fopen("mand.ppm", "wb");
fprintf(fpi, "P5\n%d %d\n255\n", dimensione, dimensione);
fwrite(matcuda, 1, dimensione*dimensione, fpi);
fclose(fpi);


cudaFree(matcuda);
return 0;
}

sabato 13 novembre 2021

Foraminifera tensorflow retraining

Dopo oltre un anno da questo post ho provato ad affrontare il riconoscimento di foraminiferi mediante rete neurale partendo dal retraining di una rete esistente piuttosto che creando una rete ex novo






Stavolta per rendere i risultati piu' coerenti ho utilizzato solo le immagini al microscopio cono risoluzione di un pixel per micron. Le immagini riprese sempre da endlessforam.org sono state private delle note utilizzando il comando mogrify di imagemagick

Per evitare di installare tutto da zero ho montato tensorflow in docker con il supporto dei notebook di jupyter

docker pull tensorflow:latest-jupyter 

dato che nel docker non e' presente la libreria tensorflow-hub ho modificato il docker creando il Dockerfile 

----------------------------------------

FROM tensorflow/tensorflow:latest-jupyter
RUN pip install --upgrade pip
RUN pip install --upgrade tensorflow-hub

----------------------------------------

in seguito 

docker build . -t tensorflor/tensorflow:latest-jupiter-hub

la rete neurale ha necessita' di occupare piu' Ram possibile ed ho disabilitato i controlli del kernel su docker in modo da non andare in OOM (Out of Memory)

La home directory della macchina e' inoltre mappata su /tf/notebook del container in modo da salvare i modelli. Infine si mappa la porta 8888 del container sulla 8888 del localhost per interagire con i notebook

sudo docker run --oom-kill-disable -m="6g" --memory-swap="10g"  -it -v $PWD:/tf/notebooks -w /tmp -p 8888:8888 tensorflow/tensorflow:latest-jupyter-hub

in alcuni casi puo' essere necessario aggiungere al file /etc/default /grub la stringa

GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"

lanciare un update-grub e riavviare la macchina

per abilitare la GPU NVidia si aggiunge lo switch --gpus all ma in questo caso la memoria utilizzabile sara' solo quella della GPU (e sui portatili di solito e' difficile avere schede grafiche con generose dotazioni di ram) e deve essere presente docker-nvidia

Le immagini dei foarminifei sono relativi a 15 classi (dati)

Usando come base efficientnetv2-s-21k-ft1k (dimensione immagine 384 pixel) con il risultato di 80% di risultati corrispondenti sul modello originale  e 68% sul dataset di validazione

il notebook puo' essere scaricato da qui

lunedì 14 giugno 2021

Lock Picking

Avevo acquistato questo lucchetto e lo avevo messo alla bici...dopo qualche giorno ho perso le chiavi. Adesso devo vendere la bici e  volevo toglierlo ... ma sono pigro per usare un seghetto

Francamente non pensavo cosi' facile



giovedì 10 giugno 2021

Eclisse solare 10 giugno 2021 Firenze ore 12:03

Immagine da telefono su oculare dell'eclisse solare del 10 giugno 2021 da Firenze


Il filtro solare devo ammettere che funziona bene...peccato non essere riusciti a montare la camera astronomica sull'oculare

questa e' versione virtuale di Stellarium



Debugger integrato ESP32S3

Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede  nell'ID USB della porta Jtag. Nel modulo...