Je suis actuellement à l'essai sur un certain usage de la stl-structures de données. Cependant, je ne suis pas encore sûr à utiliser l'un et de l'utilisation d'une certaine combinaison. Actuellement, je suis à essayer de comprendre, lors de l'utilisation d'un std::multimap
ne font sens. Aussi loin que je peux voir, on peut facilement construire votre propre multimap mise en œuvre en combinant std::map
et std::vector
. Donc, je suis parti avec la question lors de chacune de ces structures de données doit être utilisé.
- Simplicité: Un std::multimap est certainement plus simple à utiliser, parce que l'on n'a pas à gérer l'imbrication supplémentaire. Cependant, l'accès à une gamme d'éléments en vrac on pourrait avoir besoin de copier les données de la itérateurs à l'autre discbased (par exemple un
std::vector
). - Vitesse: La localité de le vecteur le plus probable fait une itération sur la plage de l'égalité élément beaucoup plus rapide, parce que l'utilisation du cache est optimisé. Cependant, je devine que
std::multimaps
y a aussi beaucoup de l'optimisation des trucs derrière le dos pour faire une itération sur les éléments égaux aussi vite que possible. Pour passer à l'élément correct de gamme pourrait probablement être optimisé pourstd::multimaps
.
Pour essayer de la vitesse de questions, j'ai fait quelques comparaisons simples en utilisant le programme suivant:
#include <stdint.h>
#include <iostream>
#include <map>
#include <vector>
#include <utility>
typedef std::map<uint32_t, std::vector<uint64_t> > my_mumap_t;
const uint32_t num_partitions = 100000;
const size_t num_elements = 500000;
int main() {
srand( 1337 );
std::vector<std::pair<uint32_t,uint64_t>> values;
for( size_t i = 0; i <= num_elements; ++i ) {
uint32_t key = rand() % num_partitions;
uint64_t value = rand();
values.push_back( std::make_pair( key, value ) );
}
clock_t start;
clock_t stop;
{
start = clock();
std::multimap< uint32_t, uint64_t > mumap;
for( auto iter = values.begin(); iter != values.end(); ++iter ) {
mumap.insert( *iter );
}
stop = clock();
std::cout << "Filling std::multimap: " << stop - start << " ticks" << std::endl;
std::vector<uint64_t> sums;
start = clock();
for( uint32_t i = 0; i <= num_partitions; ++i ) {
uint64_t sum = 0;
auto range = mumap.equal_range( i );
for( auto iter = range.first; iter != range.second; ++iter ) {
sum += iter->second;
}
sums.push_back( sum );
}
stop = clock();
std::cout << "Reading std::multimap: " << stop - start << " ticks" << std::endl;
}
{
start = clock();
my_mumap_t mumap;
for( auto iter = values.begin(); iter != values.end(); ++iter ) {
mumap[ iter->first ].push_back( iter->second );
}
stop = clock();
std::cout << "Filling my_mumap_t: " << stop - start << " ticks" << std::endl;
std::vector<uint64_t> sums;
start = clock();
for( uint32_t i = 0; i <= num_partitions; ++i ) {
uint64_t sum = 0;
auto range = std::make_pair( mumap[i].begin(), mumap[i].end() );
for( auto iter = range.first; iter != range.second; ++iter ) {
sum += *iter;
}
sums.push_back( sum );
}
stop = clock();
std::cout << "Reading my_mumap_t: " << stop - start << " ticks" << std::endl;
}
}
Comme je le soupçonnais, il dépend essentiellement du rapport entre num_partitions
et num_elements
, je suis donc toujours à une perte ici. Voici quelques exemples de sorties:
Pour num_partitions = 100000
et num_elements = 1000000
Filling std::multimap: 1440000 ticks
Reading std::multimap: 230000 ticks
Filling my_mumap_t: 1500000 ticks
Reading my_mumap_t: 170000 ticks
Pour num_partitions = 100000
et num_elements = 500000
Filling std::multimap: 580000 ticks
Reading std::multimap: 150000 ticks
Filling my_mumap_t: 770000 ticks
Reading my_mumap_t: 140000 ticks
Pour num_partitions = 100000
et num_elements = 200000
Filling std::multimap: 180000 ticks
Reading std::multimap: 90000 ticks
Filling my_mumap_t: 290000 ticks
Reading my_mumap_t: 130000 ticks
Pour num_partitions = 1000
et num_elements = 1000000
Filling std::multimap: 970000 ticks
Reading std::multimap: 150000 ticks
Filling my_mumap_t: 710000 ticks
Reading my_mumap_t: 10000 ticks
Je ne suis pas certain sur la façon d'interpréter ces résultats. Comment feriez-vous pour décider de la bonne structure de données? Existe-il des contraintes supplémentaires pour la decission, dont j'ai peut-être raté?