Ispirato alla risposta di VinyleEm, il mio suggerimento per una struttura dati personalizzata
La tua matrice è troppo grande per la memoria. Le mappe hash e gli alberi rb hanno un sovraccarico per voce e ogni voce deve memorizzare sia value
che i
, che già aggiunge fino a 8 byte escludendo il sovraccarico. Potrebbero essere necessari alcuni trucchi personalizzati per ridurre al minimo l'overhead sia della memoria che dei calcoli.
Suggerirei di suddividere le voci 2 ^ 30 in pezzi, ad es. 2 ^ 10 pezzi di (massimo) 2 ^ 20 voci ciascuno. Ogni pezzo può essere un vettore ordinato di coppie di indice e valore.
Pensando, se sono 2 ^ 15 pezzi di 2 ^ 15 voci max ciascuno, allora l'indice all'interno di ogni pezzo può essere memorizzato in due byte. Il valore è 4 byte, quindi il totale è 6 byte per voce. O qualsiasi altro break-up con 2 ^ 16 o meno voci massime.
Utilizzo totale della memoria: number_of_actual_entries * 6 byte + additional_overhead (che stimano essere di circa 1 MB). [1]
Mantenere le voci ordinate in qualsiasi momento sarà lento, quindi è meglio usare semplicemente emplace_back () e ordinare alla fine.
Questo ha il vantaggio aggiuntivo che il working set della memoria attiva è ridotto: quando si aggiungono voci, è attiva solo la fine di ogni vettore, mentre durante l'ordinamento è attivo solo un vettore. Ciò migliora il comportamento della cache e mantiene lo scambio al minimo.
std::vector<std::pair<short, int>> arr[1 << 15];
// Fill the entries
for(int i = 0; i < (1 << 28); ++i) // Whatever
{
int value = foo(i); // Or whatever you calculate
int piece = (value >> 15);
short entry = (value && 0x7fff);
arr[piece].emplace_back(entry, i);
}
// Now sort everything
for(int j = 0; j < (1 << 15); ++j)
{
std::sort(arr[j].begin(), arr[j].end(),
[](std::pair<short,int> lhs, std::pair<short,int> rhs)
{ return lhs.first < rhs.first; }
}
// Datastructure is ready to be used
[1] Alla maggior parte dei compilatori deve essere detto di non allineare quei sei byte, per evitare di sprecare altri due byte sul padding.