Archive › Marzo, 2012
c_lang

Non esagerate con i trucchetti

Greg writes:

Here’s a quick and clean way to swap data in place without having to resort to using a temporary memory location:

short *aPtr, *bPtr;

*aPtr ^= *bPtr;
*bPtr ^= *aPtr;
*aPtr ^= *bPtr;

While this is mathematically cool, lets take a look at the assembly code that it generates and see what’s really happening. First, for comparison, a couple of more pedestrian implementations:

void swap2(short *aPtr, short *bPtr) {
  short a = *aPtr; // a version with two temporaries
  short b = *bPtr;

  *aPtr = b;
  *bPtr = a;
}

void swap1(short *aPtr, short *bPtr) {
  short a = *aPtr; // a version with one temporary

  *aPtr = *bPtr;
  *bPtr = a;
}

void swap0(short *aPtr, short *bPtr) {
  *aPtr ^= *bPtr; // Greg’s tip
  *bPtr ^= *aPtr;
  *aPtr ^= *bPtr;
}

Now, let’s take a look at what the compiler actually generates for these functions. (I’m using CodeWarrior with all optimizations on for these examples.)

Recall that as processsors have gotten faster, memory has not. For instance 1/80ns (the speed on memory in most Macintoshes) = 12.5 MHz. This means that if adjacent instructions have to address memory with no intervening computation, it’s as if the processor has slowed to 12.5MHz.

First the 68K compiler, starting with the two temp case:

Name="swap2"(6) Size=26
  MOVEA.L $0004(A7),A1
  MOVEA.L $0008(A7),A0
  MOVE.W (A1),D0
  MOVE.W (A0),D1
  MOVE.W D1,(A1)
  MOVE.W D0,(A0)
  RTS

Ignoring the two MOVEA.L’s which set up the address registers and the return, this takes four instructions, all of which touch memory. Notice, however that there are no cases where the result of an instruction is used an an input to the next instruction, meaning that most of the instructions can overlap in the processor pipeline.

Next with one temp:

Name="swap1"(4) Size=24
  MOVEA.L $0004(A7),A1
  MOVEA.L $0008(A7),A0
  MOVE.W (A1),D0
  MOVE.W (A0),(A1)
  MOVE.W D0,(A0)
  RTS

Here we have three instructions, all accessing memory and all can overlap. This is smaller than the example above. Whether it is faster depends on the relative timing of the MOVE.W (A0),(A1) instruction. (If anyone wants to time this, I’ll print the results.)

Now Greg’s ‘tip’:

Name="swap0"(1) Size=30
  MOVEA.L $0004(A7),A1
  MOVEA.L $0008(A7),A0
  MOVE.W (A0),D0
  EOR.W D0,(A1)
  MOVE.W (A1),D0
  EOR.W D0,(A0)
  MOVE.W (A0),D0
  EOR.W D0,(A1)
  RTS

This generates six instructions, all of which touch memory. Furthermore three of these are read-modify-write cycles, which are slower that a read or write and each instruction depends on the result of the instructon directly before it, meaning it won’t overlap in the pipeline, making this both the largest and slowest implementation of the three.

Now lets look at the PowerPC code:

Name=".swap2"(6) Size=20
  lha r0,0(r3)
  lha r5,0(r4)
  sth r5,0(r3)
  sth r0,0(r4)
  blr

Name=".swap1"(4) Size=20
  lha r5,0(r3)
  lha r0,0(r4)
  sth r0,0(r3)
  sth r5,0(r4)
  blr

Note that both of the versions with temporaries generated the same code (4 instructions, all touching memory but pipelineable). This is because RISC processors typically don’t have memory to memory operations; instead, they must move data to a register before operating on it.

Now our ‘tip’:

Name=".swap0"(1) Size=52
  lha r5,0(r4)
  lha r0,0(r3)
  xor r0,r0,r5
  sth r0,0(r3)
  lha r5,0(r3)
  lha r0,0(r4)
  xor r0,r0,r5
  sth r0,0(r4)
  lha r4,0(r4)
  lha r0,0(r3)
  xor r0,r0,r4
  sth r0,0(r3)
  blr

This implementation is by far the largest and slowest, generating 12 instructions, including 6 memory accesses. Furthermore there are 2 pipeline stalls. Clearly this implementation is the largest and slowest of all.

The moral of the story is: don’t get tricky. C programmers often try to minimize the number of lines of C in their program without consideration for what the compiler will generate. When in doubt, write clear code and give the optimizer a chance to maximize performance. Look at the compiler output. Your code will be easier to debug and probably faster too.

’Till next time

Comments ( 0 )
freenas_logo

Copia chiave ssh su freenas

FreeNas utilizza il filesystem di root in modalità sola lettura.
Quando andiamo a copiarci una chiave ssh per poter copiare via scp o per connetterci attraverso ssh senza la richiesta della password dobbiamo fare quanto segue:

Montare il filesyste in lettura/scrittura:

workstation# ssh [email protected]
[email protected]'s password: xxxxxx
nas# mount -o rw /dev/ufs/FreeNASs1a

copiare, dalla macchina con cui ci collegeremo, la chiave ssh:

workstation# ssh-copy-id [email protected]

 
montare nuovamente il filesystem del nas in sola lettura:

nas# mount -o ro /dev/ufs/FreeNASs1a

fa-fa-fatto.

Comments ( 0 )
ramdisk-150x150

Ram Disk sul Mac

Con Ram Disk si indica una porzione di memoria RAM utilizzata come se fosse una normale unità a dischi.
Ovviamente, utilizzando memoria volatile, una volta che il Mac è stato riavviato o spento, tutti i dati che erano presenti nel disco virtuale saranno persi.

Ecco come ottenere un disco su Ram per il vostro Mac.

Aprite un terminale e digitate (o copiaincollate) queste istruzioni per una Ram Disk da 4GB:

diskutil erasevolume HFS+ “ramdisk” `hdiutil attach -nomount ram://8000000`

Se vogliamo modificare la dimensione della Ram Disk possiamo variare l’ultimo parametro.
2000000 per una Ram Disk da 1GB, 4000000 per una Ram Disk da 2GB.

Per rimuovere la Ram Disk è sufficiente espellerla come un comune disco hot-plug.

Comments ( 0 )
Logo_di_Mozilla_Thunderbird

Backup profilo di Thunderbird su OsX

Per effettuare il backup del profilo di posta su OsX dobbiamo per prima cosa trovare il profilo.

Se avete effettuato l’installazione standard il vostro profilo di posta si troverà nella cartella:

/Users/UTENTE/Library/Thunderbird/profiles

dove, ovviamente, UTENTE è il vostro username.

Per aprire una finestra del Finder a quell’indirizzo potete, sempre dal Finder, andare sul menù “Vai“, scegliere la voce “Vai alla cartella…” ed inserire l’indirizzo:

~/Library/

(per inserire il carattere ~ usate ALT-5)

Nella finestra troverete la cartella “Thunderbird” che contiene il file “profiles.ini” e la cartella con il profilo stesso. Per essere certi che quella è realmente la cartella contenente il profilo potete controllarne la dimensione o il contenuto.

Potete a questo punto fare click con il bottone destro del mouse e scegliere “Comprimi Thunderbird” per ottenere un archivio compresso della cartella di cui effettuare il backup. Copiate l’archivio su un supporto esterno o su una condivisione in rete.

Se invece l’installazione di Thunderbird non è stata effettuata in modo standard oppure volete controllare ulteriormente dove risiede il profilo contenente la posta potete procedere così:

Aprite Thunderbird, menù Strumenti >> Impostazioni Account.

Nella parte sinistra troverete gli account di posta configurati. Per ogni account potete controllare, alla voce “Impostazioni server“, la path completa della cartella locale (appena selezionata la voce “Impostazioni server” trovate questo path in basso a destra della stessa finestra)

Ripristino

Per effettuare il ripristin reinstallate Thunderbird e avviatelo. Appena richiede di configurare gli account di posta annullate l’operazione e chiudete completamente il programma.

Andate di nuovo nella cartella della libreria:

~/Library/

e scompattate l’archivio creato in precedenza.

Se avete intenzione di mettere il profilo di posta in un’altra posizione potete semplicemente spostare la cartella xxxxxxxx.default contenuta nella cartella profiles dove volete (e magari rinominarla con un nome un pò più comprensibile) e modificare il file di testo che definisce la posizione dei profili – profiles.ini – che trovate sempre dentro la cartella ~/Library/Thunderbird/.

In questo file basta modificare il valore del campo IsRelative mettendolo a zero (0) e modificare la path del profilo inserendo la path completa dove avete spostato il profilo contenente la mail (p. es. ~/Posta/MiaPosta)

Per modificare il file di testo potete utilizzare l’ottimo “Fraise” (link su MacUpdate…)

buon divertimento

 

Comments ( 0 )
210px-Python

Estrarre URL immagini da un css

Ecco un banale script python per estrarre gli url delle immagini da un file css
Nel file gli url saranno nella forma: url(‘http://www.qualcosa.com/immagine.png’)

#!/usr/bin/python
import string, os

f=open("file.css", "r")

allf=f.read()

while string.find(allf, 'url') > 0:
    a = string.split(allf, "url(\'", 1)
    b = string.split(a[1], "\')", 1)
    print b[0]
    allf = b[1]
Comments ( 0 )