Questa è una sorta di follow-up di questa domanda originale con alcune nuove informazioni aggiunte. Vedi qui per la prima parte se sei interessato: Struct of arrays, arrays of structs and memory usage patternStrutturazione di array e modelli di accesso alla memoria
Sembra che ci siano alcuni problemi con il mio primo tentativo di impostare la struttura degli array per una classe semplice. Essenzialmente si tratta di allocazione di memoria in eccesso per i puntatori e possibili perdite di memoria dall'allocazione di quei puntatori da vec3_b nella domanda precedente.
Ho pensato a come riordinare i dati senza usare i puntatori, questo mi impone di impostare prima alcune variabili const per la dimensione dei miei bucket di dati, quindi nessun valore illimitato come puntatori ma riduce anche la quantità di memoria a qualcosa di fisso.
const size_t batch_size = 100;
struct vec3_c
{
size_t x[batch_size];
size_t y[batch_size];
size_t z[batch_size];
};
struct vec3_c vec3_c(size_t x, size_t y, size_t z, size_t index)
{
struct vec3_c v;
v.x[index] = x;
v.y[index] = y;
v.z[index] = z;
return v;
}
struct vec3_c vc3;
for(int i = 0; i < batch_size; i++)
{
vc3 = vec3_c(i+1, i*i, i*10, i);
//printf("vec3c x:%zu, y:%zu, z:%zu\n",vc3.x[i], vc3.y[i], vc3.z[i]);
printf("vec3c x:%p, y:%p, z:%p\n",(void*)&vc3.x[i], (void*)&vc3.y[i], (void*)&vc3.z[i]);
}
---------------x-----------------|----------------y-----------------|----------------z-----------------|
0| 0x7fff57489f40 : 140734657765184 | 0x7fff5748a260 : 140734657765984 | 0x7fff5748a580 : 140734657766784
1| 0x7fff57489f48 : 140734657765192 | 0x7fff5748a268 : 140734657765992 | 0x7fff5748a588 : 140734657766792
2| 0x7fff57489f50 : 140734657765200 | 0x7fff5748a270 : 140734657766000 | 0x7fff5748a590 : 140734657766800
con questo codice aggiornato devo avere una dimensione fissa secchio così mi sono messo a batch_size di 100 solo per i numeri semplici. Riempi il vec3c con alcuni dati e fai un test simile, questa volta sembra che ogni valore sia allineato in blocchi da 8 byte.
es:
size of vec3 : 24 bytes
size of vec3a : 24 bytes
size of vec3b : 24 bytes
size of vec3c : 2400 bytes
size of size_t : 8 bytes
size of int : 4 bytes
size of 16 int : 64 bytes
vec3c x:0x7fff592d2f40, y:0x7fff592d3260, z:0x7fff592d3580
vec3c x:0x7fff592d2f48, y:0x7fff592d3268, z:0x7fff592d3588
vec3c x:0x7fff592d2f50, y:0x7fff592d3270, z:0x7fff592d3590
vec3c x:0x7fff592d2f58, y:0x7fff592d3278, z:0x7fff592d3598
vec3c x:0x7fff592d2f60, y:0x7fff592d3280, z:0x7fff592d35a0
vec3c x:0x7fff592d2f68, y:0x7fff592d3288, z:0x7fff592d35a8
vec3c x:0x7fff592d2f70, y:0x7fff592d3290, z:0x7fff592d35b0
vec3c x:0x7fff592d2f78, y:0x7fff592d3298, z:0x7fff592d35b8
vec3c x:0x7fff592d2f80, y:0x7fff592d32a0, z:0x7fff592d35c0
vec3c x:0x7fff592d2f88, y:0x7fff592d32a8, z:0x7fff592d35c8
sono separate da 8 byte.
Questo dovrebbe eliminare i problemi di perdite di memoria e la memoria in eccesso necessaria per i puntatori.
con questo essendo il nuovo layout qualcosa come sizeof (vc3 [0] .x) restituirebbe 8 byte.
nuovo alle domande originali:
È il mio attuazione
struct vec3_c
il modo corretto di impostare una struttura di array?con una dimensione di batch vec_3c di 100 mostra 2400 byte di larghezza ma ogni singolo elemento è solo 8 byte e allineato correttamente, quindi ora posso inserire 8 elementi su 1 linea di cache cpu moderna?
trasformerebbe i dati passati a me in un formato tipico di soli array di strutture superiori ai benefici di prestazioni di essere in uno stato di cache friendly e in grado di operare su più punti di dati per chiamata di istruzioni? Questo è con l'avvertenza che entrambi i punti 1 e 2 sono corretti.
ex facendo il prodotto scalare di due vettori: che significa che ho potuto ottenere il prodotto scalare di 2 vec3_c per ciclo di istruzione?
modificare ancora una domanda, sarebbe meglio per aggiungere le ulteriori 8 byte di dati per rendere questa struct è un multiplo di 32 byte e magari utilizzare tale ulteriore 8 byte come spazio zero o semplicemente lasciare vuoto?
modifica Mi è stato fatto notare che la mia funzione di inizializzazione iniziale stava solo facendo un casino di cose.Ho aggiornato a questa forma:
struct vec3_c* vec3_c()
{
struct vec3_c *v = (struct vec3_c*)malloc(sizeof(struct vec3_c));
v->index = 0;
return v;
}
struct vec3_c* v3 = vec3_c();
for(size_t i = 0; i < batch_size; i++)
{
v3->x[i] = i + 1;
v3->y[i] = i * i;
v3->z[i] = i * 10;
printf("index:%d\tvec3c x:%zu, y:%zu, z:%zu\n",i,v3->x[i], v3->y[i], v3->z[i]);
printf("index:%zu\tvec3c x:%p, y:%p, z:%p\n",i,(void*)&v3->x[i], (void*)&v3->y[i], (void*)&v3->z[i]);
}
Spiacente, forse sto interpretando erroneamente l'intero problema, ma mi sembra che si stia utilizzando vc3 an v in modo errato: infatti, la funzione vec3_c alloca una "v" locale (non inizializzata), quindi imposta SOME campi e restituisce una COPIA OF v (i cui campi contengono valori imprevedibili, ad eccezione di "index"). Vedo che nel tuo esempio non sei realmente interessato al contenuto di vc3, quindi qual è lo scopo della funzione vec3_c? –
@GiuseppeGuerrini il mio esempio di codice iniziale aveva alcuni bug che ho risolto nel tempo. Vorrei usare questa struttura per elaborare in batch i valori di vec3 qualcosa come un'elaborazione del flusso o istruzioni di tipo SIMD. – user1610950