KiloHertz, MegaHertz, GigaHertz, …. #2

Nella prima parte abbiamo stabilito che ogni singola istruzione eseguita dal microprocessore è suddivisa in stati.

In base al tipo di microprocessore varia il numero di stati associati ad ogni istruzione, consideriamo per esempio l’istruzione NOP (no operation):

ebbene si, esiste un comando per dire al microprocessore di non fare nulla, ma di questo parleremo un’altra volta….

Confronteremo il numero di cicli di clock necessari per eseguire il comando NOP su 3 microprocessori a 8 bit preistorici (cioè di quando ero giovane).

INTEL8080 il primo processore a 8 bit di INTEL 4 cicli
MOS Technology 6502 utilizzato da APPLE per il suo APPLE IIe 2 cicli
ZILOG Z80 il cui successo è legato alla diffusione del s.o. CP/M 4 cicli

Già da questo esempio notiamo differenze abbastanza rilevanti, inoltre il 6502 implementa un meccanismo di pipeline per cui mentre esegue l’istruzione NOP nel secondo ciclo di clock, sta già leggendo l’istruzione successiva.

L’affare si complica!

(segue)

Un po’ di storia #1

270px-Intel_4004

Quando nel 1971 andò in produzione il primo microprocessore Intel 4004, al cui progetto lavorò anche l’italiano Federico Faggin, nessuno immaginava che nel giro di pochi anni questa tecnologia sarebbe diventata il cuore dei Personal Computer: nel 1974 venne messo in commercio l’ALTAIR8800 della MITS basato sull’Intel 8080.

Prima dell’ALTAIR i progettisti consideravano i microprocessori come dei validi rimpiazzi per la logica cablata nei sistemi di controllo. Per esempio per controllare una lavatrice, è necessario realizzare una rete logica che ad ogni variazione dello stato degli ingressi (pulsanti, interruttori, sensori di livello, sensori di temperatura ecc) produce una conseguente variazione dello stato delle uscite (che comandano il motore, le resistenze di riscaldamento dell’acqua, le elettrovalvole ecc.). Questa rete logica non può essere una semplice rete combinatoria, poichè il sistema controllato prevede dei cicli di lavoro soggetti a temporizzazioni, pertanto la rete logica viene implementato come automa a stati finiti. Questo approccio è ampiamente collaudato e quindi, al di là di gestire la complessità legata per esempio all’esigenza di gestire sulla lavatrice differenti programmi di lavaggio dove sta il vantaggio di utilizzare un sistema a microprocessore? Il vantaggio risiede nel fatto che una volta definita l’architettura hardware della scheda di controllo a microprocessore tutta la logica di funzionamento della lavatrice dipende esclusivamente dal software,  diversamente dal sistema a logica cablata nel quale ogni variazione della logica di funzionamento del sistema controllato richiede la riprogettazione della rete logica.

L’Intel 4004 non fu creato per gestire una lavatrice, ma per realizzare una calcolatrice da tavolo. Grazie alla flessibilità del microprocessore questo disposivito potè essere utilizzato per calcolatrici, lavatrici, linee di produzione industriale e infine approdò al mondo dei Personal Computer.

(segue)

What’s a Symbol?

In Ruby esistono due modi per definire un dato di tipo testuale:

il primo utilizza la classe String, il secondo utilizza la classe Symbol:

a = "lettera_a"
b = :lettera_b

utilizzando il metodo class possiamo verificare che a è un oggetto di classe String invece b è un oggetto di classe Symbol.

se creiamo altri due oggetti con le stesse espressioni letterali possiamo notare una cosa:

a2 = "lettera_a"
b2 = :lettera_b
a.object_id == a2.object_id       # false
b.object_id == b2.object_id       # true

le stringhe a ed a2, nonostante abbiano lo stesso contenuto, sono oggetti diversi!

invece i simboli b e b2 sono in realtà lo stesso simbolo.

Ora se creo un simbolo b3 convertendo una stringa con il contenuto “lettera_b” anche questo sarà una ulteriore istanza del simbolo :lettera_b

b3 = "lettera_b".to_sym
b3.object_id == b2.object_id         # true

Quanto osservato ha due implicazioni: la prima è che utilizzando i simboli al posto delle stringhe utilizziamo meno memoria, la seconda, più rilevante, è che dovendo confrontare due simboli l’interprete Ruby si limita a confrontare gli object_id, operazione ben più veloce di un confronto carattere per carattere.

 

 

KiloHertz, MegaHertz, GigaHertz, …. #1

Quanto è veloce un microprocessore?

Per rispondere a questa domanda dobbiamo prima renderci conto della relazione che intercorre tra il clock di un sistema a microprocessore e l’effettiva velocità di esecuzione di un programma. Andiamo per gradi.

Quando un microprocessore esegue del codice, lo fa ripetendo continuamente lo stesso ciclo:

  1. leggi l’istruzione corrente
  2. esegui l’istruzione corrente
  3. punta all’istruzione successiva

al termine riparte dal punto 1.

Queste tre semplici frasi riassumono operazioni che hanno una loro complessità, cosa intendiamo con i verbi leggere ed eseguire? cosa significa istruzione corrente ed istruzione successiva?

Ogni sistema a microprocessore è dotato di una memoria in cui è contenuto il codice del programma, possiamo pensare alla memoria come ad una lista di elementi identificati da un numero progressivo (un array). Ogni sistema a microprocessore è anche dotato di un registro (chiamato program counter) che indirizza la memoria di programma, cioè punta ad un elemento della lista.

L’operazione 1 indica il trasferimento dell’elemento puntato dal program counter in uno speciale registro che chiameremo registro istruzioni.

Con l’operazione 2 il contenuto del registro istruzioni viene decodificato e viene eseguita una operazione che dipende dal contenuto del registro stesso. In base al tipo di microprocessore avremo da poche decine a svariate centinaia di possibili istruzioni.

L’operazione 3 incrementa il registro istruzioni affinchè questo punti alla successiva istruzione.

Eseguendo all’infinito questo ciclo vengono svolte sequenzialmente tutte le istruzioni contenute nella memoria di programma.

Sappiamo che un generico algoritmo non contiene solo sequenze lineari di operazioni ma possiamo avere diramazioni oppure cicli.  Per alterare la sequenza lineare di esecuzione del codice di programma è sufficiente disporre di istruzioni che alterino il program counter, quando il ciclo visto prima riparte dal punto 1 non leggerà l’istruzione successiva ma piuttosto quella puntata dal valore assunto in quell’istante dal program counter.

In queste poche righe abbiamo descritto l’essenza del funzionamento di qualsiasi sistema a microprocessore.  Abbiamo anche capito che il funzionamento di ogni programma è conseguenza dell’esecuzione delle singole istruzioni contenute nella memoria di programma.

In base al tipo di microprocessore ogni istruzione elementare richiede un numero variabile di cicli di clock per la sua esecuzione.

(segue)

RoR 4.1.0 beta 1 released!

ror

E’ Natale e il regalo di quest’anno è l’anteprima di Ruby On Rails 4.1

Spring Application Preloader

Spring velocizza lo sviluppo mantenendo l’applicazione in esecuzione in background,  evitando di riavviarla ogni volta che dovete eseguire un task di rake, una migrazione oppure un test.

config/secrets.yml

Questo files, che di default memorizza il parametro secret_key_base dell’applicazione, può essere utilizzato anche per memorizzare le chiavi di accesso per altre API externe.

Per esempio possiamo mantenere l’access key dei web services amazon

development:
  secret_key_base: 3b7cd727ee24e8444053437c36cc66c3
    aws_access_key: 09876543212345678
ed accedervi quando necessario nell’applicazione
aws_acc_key = Rails.application.secrets.aws_access_key

Action Pack Variants

I request variant  sono una specializzazione dei request format
che consentono di effettuare render differenziati in base al dispositivo da cui avviene la richiesta:

respond_to do |format|
    format.js      { ...... }
    format.desktop    { ....... }
    format.phone  { ....... }
    format.tablet   { ....... }
end

il variant deve essere impostato in una before_action

request.variant = :tablet if request.user_agent =~ /iPad/

Action Mailer Previews

Visitando uno speciale url è possibile visualizzare in anteprima l’aspetto delle email prodotto dall’Action Mailer.

Active Record Enums

Ora è possibile associare dei nomi ai valori numerici di un campo intero di una tabella.
Class Invoice < ActiveRecord::Base
        enum status: [ :suspended, :active, :payed ]
end

if status.payed? ......
………….. prosegue nel prossimo articolo …………..