Domanda

Mi piacerebbe sapere se un qualche tipo di struttura contiene più di una primitiva, ma la sua dimensione totale è inferiore o uguale a dimensione di un singolo registro della CPU come un registro 4 byte, fa sempre senso per un compilatore metterlo in uno di questi registri di 4 byte quando passa dal valore o riferimento a una funzione invece di fare una copia in pila Chiamato o passando un puntatore ad esso ed in generale quando passa qualcosa di più di un singolo a primitiva una funzione come una matrice o una struttura potrebbe passare in una CPU registro sempre tornare utile?

campione di tale struttura:

struct sample{
 public:
  char char1;
  char char2;
};

campione passando la struttura a una funzione:

void someFunc(const sample input){
 //whatever
}
void someFunc(sample input){
 //whatever
}
void someFunc(sample & input){
 //whatever
}
void someFunc(const sample & input){
 //whatever
}
È stato utile?

Soluzione

Sì. Molti compilatori hanno una speciale attributo parola chiave o il tipo che è possibile utilizzare per specificare che una struttura dovrebbe essere passato in registri piuttosto che in pila. È più comune su processori che hanno molti registri e condutture profonde, come PowerPC, e può essere un enorme miglioramento delle prestazioni in architetture dove scrittura di un valore di memoria e quindi leggere nuovamente indietro subito provoca uno stallo pipeline.

Di solito si userebbe solo per una struttura che è la stessa dimensione di un registro nativo. In particolare, è utile su processori che hanno un'ampia SIMD registri, che possono passare 16 byte alla volta o più. Ciò permetterà di passare (per esempio) un vettore 4 dimensionale (quattro carri) su un registro. AMD System V è un esempio di un ABI x86 che consente questo.

Un esempio diverso è attributo type d64_abi di GCC, che indica un PowerPC passare una struttura su registri ove possibile, anziché in pila. (Questo fa parte della Darwin ABI ).

typedef struct {
    int          a;
    float        f;
    char         c;
} __attribute__ ((d64_abi)) Thingy;

Thingy foo( Thingy t );

Nel caso precedente, una chiamata verso Foo passare la Thingy su un registro galleggiante e due registri int, piuttosto che scrivere alla pila e la lettura di destra di nuovo. Il valore di ritorno torna sui registri nello stesso modo.

Non ho mai visto un compilatore che fa automaticamente, senza il tuo dire, ma è possibile uno esiste.

Altri suggerimenti

Questo è definito nel interfaccia applicativa binaria (ABI) del vostro ambiente di esecuzione. La norma non dice nulla su registri del processore quando viene chiamata una funzione, quindi è legale per creare un ambiente in cui le strutture di piccole dimensioni sono imballati in un singolo registro del processore.

Per la parte di riferimento, sono molto suscettibili di essere passati come puntatori in ogni caso, dal momento in cui all'interno della funzione chiamata è preso l'indirizzo di un riferimento, si deve risolvere l'indirizzo dell'oggetto referenziato.

In alcune architetture (come i386, lo so che è antica, ma è quello che ho cresciuto con;) certamente il senso di passare in un registro, in quanto spingendo e popping dalla pila prendere molto di più (dico tra il 3 -6 volte più cicli di CPU) come passando dal registro. Quindi, un compilatore avrebbe fatto un buon lavoro ottimizzando per questo.

Posso immaginare che ci sono altre architetture in cui non importa. O se i registri sono in uso per altre ottimizzazioni che producono più di miglioramento, non ha senso di usarli per questo.

Quale architettura stai usando / mira, o stai chiedendo in generale?

penso che ci sia compilatori che passerà POD nei registri, anche se sono structs.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top