Mi sono imbattuto in uno strano comportamento di std :: set.std :: set veloce e lento, cosa sta succedendo?
Ecco il codice:
#include <cstdio>
#include <windows.h>
#include <stdlib.h>
#include <vector>
#include <set>
using namespace std;
int main(int argc, char *argv[])
{
set<int> b[100];
for (int o=0; o<10; o++)
{
int tt = GetTickCount();
for (int i=0; i<5000000; i++)
{
b[o].insert(i);
}
tt = GetTickCount() - tt;
b[o].clear();
printf("%d\n", tt);
}
return 0;
}
Sono in esecuzione su Windows XP.
Ecco la parte interessante: questa prima volta stampata è di circa 3500 ms, mentre tutti i successivi sono oltre 9000 ms! Perché sta succedendo?
Oh, e questo accade solo nella versione di rilascio (ottimizzazione -O2).
Non succede su Linux (dopo aver modificato il codice per compilare lì).
Un'ultima cosa: quando lo eseguo mentre eseguo il profiling con Intel VTune ci vogliono sempre circa 3000 ms, quindi è così che dovrebbe essere.
UPDATE: Ecco il codice nuovo:
#include <cstdio>
#include <windows.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
const int count = 10000000;
int **a = new int*[count];
for (int o=0; o<10; o++)
{
int ttt = GetTickCount();
for (int i=0; i<count; i++)
{
a[i] = new int;
*a[i] = i;
}
int ttt2 = GetTickCount();
for (int i=0; i<count; i++)
{
int r1 = rand() * 10000 + rand();
int r2 = rand() * 10000 + rand();
r1 = r1%count;
r2 = r2%count;
int *e = a[r1];
a[r1] = a[r2];
a[r2] = e;
}
int ttt3 = GetTickCount();
for (int i=0; i<count; i++)
{
delete a[i];
}
int ttt4 = GetTickCount();
printf("%d %d\n", ttt2-ttt, ttt4-ttt3);
}
return 0;
}
Questo è lo stesso problema. Quello che succede è che alloco molti molti piccoli oggetti e poi li elimini in ordine casuale - quindi è simile a come appare in std :: set. Quindi questo è un problema di gestione della memoria di Windows. Non può davvero gestire bene molti piccoli allocazioni e cancellazioni.
Questo è probabilmente correlato ad alcuni dettagli di implementazione della libreria/piattaforma standard.Potresti provare a eseguirlo in un profiler e controllare dove viene speso il tempo. Ci possono essere molte cose in corso, dalle differenze nello schema di allocazione del primo e dei passaggi consecutivi (hai rilasciato la memoria) a qualsiasi altra cosa. Si noti inoltre che è necessario utilizzare -O3 per le prestazioni. –
Forse è correlato alla pianificazione del thread di sistema. Il thread non è l'unico che richiede tempo del processore. Puoi usare 'GetThreadTimes' per vedere quanto tempo di processore consuma il tuo thread – valdo
La tua migliore scommessa potrebbe essere quella di guardare il codice assembly generato con' -O2' per vedere se c'è qualcosa che potrebbe spiegare questo comportamento. – NPE