ho una struct di 4 campi di tipi che provengono da parametri di modello:ottimale confezionamento di una struct in modo ricorsivo su modelli senza perdita di allineamento
template <typename T1, typename T2, typename T3, typename T4>
struct __attribute__((aligned(8))) four_tuple {
typedef struct {
T1 t1;
T2 t2;
T3 t3;
T4 t4;
} payload;
payload p;
};
Ogni tipo T1
, T2
, T3
, e T4
, è garantito per essere un tipo primitivo o un tipo four_tuple<...>::payload
. Le garanzie sono ricorsive: si può pensare alla struct come codifica a quadtree i cui nodi foglia sono tipi primitivi.
Il mio obiettivo è che la struttura abbia il minimo possibile sizeof
, a condizione che tutti i nodi foglia siano allineati correttamente. Gli strumenti consentiti per l'ottimizzazione sono specializzazioni modello di classe che utilizzano:
- riordino dei campi
t1
,t2
,t3
,t4
- aggiunta di campi di riempimento
- attributi gcc
packed
supayload
- forse altri?
Mi sento come se ci fosse una soluzione intelligente a questo problema utilizzando enable_if
e SFINAE. Qualcuno può trovarlo?
Per illustrare il problema, se utilizziamo l'implementazione di cui sopra come using Foo = four_tuple<char,double,char,double>
, avremo una dimensione di 32 per il carico utile e nel complesso. Se dichiariamo semplicemente il carico utile packed
, gli double
non saranno ben allineati. Una specializzazione di modello che riordina i campi in ordine decrescente (qui, double, double, char, char
) darà un carico utile e una dimensione complessiva di 24. Ma i 6 byte aggiuntivi che utilizza sono dispendiosi, come si può vedere considerando using Bar = four_tuple<Foo::payload,int,int,int>
. Con l'imballaggio ottimale Bar
è possibile inserire 32 byte, ma con questo schema ne occorrerebbero 40. L'applicazione semplice del riordino del campo con packed
comporterà un disallineamento di int
in Bar
- è necessario un riempimento.
So che in generale la ristrutturazione del layout di memoria dei campi di una struct può avere implicazioni sulle prestazioni a causa di considerazioni sulla cache, e che in generale tali implicazioni saranno almeno altrettanto significative di qualsiasi potenziale guadagno derivante da un migliore imballaggio. Mi piacerebbe esplorare i compromessi, però, e non posso davvero farlo correttamente nel mio contesto senza risolvere questo problema.
Non lo vedo. Se riordini il modo in cui hai descritto, ma non aggiungi 'packed', qual è il problema? Usarlo in un altro tipo non darebbe alcun campo disallineato, dal momento che il compilatore lo aggiusterà già con il padding. – hvd
BTW, perché forzate l'allineamento sulla vostra struct? Se i tuoi tipi sono quattro 'char's, vuoi una dimensione di 4, non è vero? Questo non può richiedere un allineamento di 8. – hvd
@hvd 'four_tuple' può raggiungere una dimensione di 32 senza disallineamenti se adeguatamente imballato. Se non si aggiunge 'packed', avrà una dimensione di 40. –
dshin