Background: Così sto lavorando su un raytracer .. per la mia costruzione del schema di partizionamento spaziale, inizialmente ho avuto qualche codice come questo:Misterioso puntatore legati multithreading rallentamento
if (msize <= 2) { // create a leaf node
Model **models = new Model*[msize];
for (uint i=0; i<msize; ++i)
models[i] = &mlist[i];
*arrayPtr = Node(models, msize); // class Node contains a copy of models
... increment arrayPtr ...
return;
}
In sostanza, dopo questo spaziale l'albero di partizionamento è costruito, i raggi attraversano l'albero alla ricerca di modelli, che sono tutti memorizzati in un unico grande array. I nodi foglia contengono i puntatori in una serie di puntatori di Modelli.
Poi ho capito che hey, non c'è motivo per me di aggiungere quel livello extra di indirezione; se sistemo correttamente i miei modelli, posso ottenere i nodi foglia per puntare direttamente alla grande serie di modelli. I modelli adiacenti tra loro nel grande array appartengono tutti a un determinato nodo foglia, quindi le foglie conterrebbero i puntatori ai Modelli. Così ho fatto questo e l'ho testato con tutto il resto tenuto costante.
Ora si potrebbe pensare che questo ovviamente accelererebbe il programma. Bene, velocizza la versione single-threaded (di circa il 10%), ma rallenta quella multithreaded (di circa il 15%! Che è abbastanza significativo se stai facendo pesanti ottimizzazioni.) Sono abbastanza ad un perdita su come affrontare questo problema - pensavo che l'indirezione fosse negativa, pensavo che ridurre l'utilizzo della memoria fosse buono, in particolare per il multithreading .. non c'è nessuna scrittura sul nodo foglia o sul modello, tutta la scrittura viene eseguita su una struttura dati separata .
Qualsiasi suggerimento/suggerimento su come analizzare il problema sarebbe ottimo.
Alcune statistiche varie: cachegrind mi dice che ci sono meno errori di istruzioni/errori di cache per l'approccio a doppio-indiretto, ma più errori di dati/errori di cache. La differenza non è poi così grande, per entrambi.
Edit: Come richiesto, la struttura dei dati che mi riguarda con:
class Node {
ushort type;
union {
ushort axisID;
ushort childrenSize;
};
union {
Model **models;
Node *rightChild;
};
float leftPlane, rightPlane;
... public methods and stuff ...
}
Io fondamentalmente cambia Model **models
-Model *models
, in tanto sono il tuffo velocità. La classe Model
contiene un puntatore a due classi astratte, Shape
e Material
. Tutte le classi menzionate qui sono allocate in blocco, con l'eccezione di Material
poiché al momento ne sto usando solo una.
È possibile pubblicare le due versioni delle strutture dati che si stanno confrontando? –
Problemi di aliasing, forse? Questo è praticamente il mio primo pensiero quando vedo un sindacato in C/C++. Quale funzione specifica dice il profiler diventa più lenta? Hai guardato al disassemblaggio per vedere se esistono differenze? – jalf
Come si condividono i dati tra i thread? – Malkocoglu