web-dev-qa-db-fra.com

Le moyen le plus rapide de réinitialiser chaque valeur de std :: vector <int> sur

Quel est le moyen le plus rapide de réinitialiser chaque valeur d'un std::vector<int> à 0 et de conserver la taille initiale du vecteur? 

Une boucle for avec l'opérateur []? 

145
Matthieu Riegler
std::fill(v.begin(), v.end(), 0);
264
Cat Plus Plus

Comme toujours lorsque vous posez la question la plus rapide: mesurez! Utilisation des méthodes ci-dessus (sur un Mac utilisant Clang):

Method      |  executable size  |  Time Taken (in sec) |
            |  -O0    |  -O3    |  -O0      |  -O3     |  
------------|---------|---------|-----------|----------|
1. memset   | 17 kB   | 8.6 kB  | 0.125     | 0.124    |
2. fill     | 19 kB   | 8.6 kB  | 13.4      | 0.124    |
3. manual   | 19 kB   | 8.6 kB  | 14.5      | 0.124    |
4. assign   | 24 kB   | 9.0 kB  | 1.9       | 0.591    |

en utilisant 100 000 itérations sur un vecteur de 10000 ints.

Edit: Si vous modifiez de manière plausible les temps résultants, vous pouvez avoir la certitude un peu _ (mais pas aussi bonne que l'inspection du code d'assemblage final) que le repère artificiel n'a pas été optimisé. Bien sûr, il est préférable d’envoyer les performances dans des conditions réelles . end Edit  

pour référence le code utilisé: 

#include <vector>

#define TEST_METHOD 1
const size_t TEST_ITERATIONS = 100000;
const size_t TEST_ARRAY_SIZE = 10000;

int main(int argc, char** argv) {

   std::vector<int> v(TEST_ARRAY_SIZE, 0);

   for(size_t i = 0; i < TEST_ITERATIONS; ++i) {
   #if TEST_METHOD == 1 
      memset(&v[0], 0, v.size() * sizeof v[0]);
   #Elif TEST_METHOD == 2
      std::fill(v.begin(), v.end(), 0);
   #Elif TEST_METHOD == 3
      for (std::vector<int>::iterator it=v.begin(), end=v.end(); it!=end; ++it) {
         *it = 0;
      }
   #Elif TEST_METHOD == 4
      v.assign(v.size(),0);
   #endif
   }

   return EXIT_SUCCESS;
}

Conclusion: utilise std::fill (car, comme d'autres l'ont dit le plus idiomatique)!

121
Fabio Fracassi

Qu'en est-il de la fonction membre assign?

some_vector.assign(some_vector.size(), 0);
21
fredoverflow

Si c'est juste un vecteur d'entiers, je commencerai par essayer:

memset(&my_vector[0], 0, my_vector.size() * sizeof my_vector[0]);

Ce n'est pas très C++, donc je suis sûr que quelqu'un fournira la bonne façon de faire cela :)

12
unwind

essayer 

std::fill

et aussi

std::size siz = vec.size();
//no memory allocating
vec.resize(0);
vec.resize(siz, 0);
2
nttstar

J'avais la même question mais à propos de vector<bool> plutôt court (autant que je sache, le standard permet de le mettre en œuvre en interne différemment d'un tableau continu d'éléments booléens). J'ai donc répété les tests légèrement modifiés de Fabio Fracassi. Les résultats sont les suivants (fois, en secondes):

            -O0       -O3
         --------  --------
memset     0.666     1.045
fill      19.357     1.066
iterator  67.368     1.043
assign    17.975     0.530
for i     22.610     1.004

Donc, apparemment, pour ces tailles, vector<bool>::assign() est plus rapide. Le code utilisé pour les tests:

#include <vector>
#include <cstring>
#include <cstdlib>

#define TEST_METHOD 5
const size_t TEST_ITERATIONS = 34359738;
const size_t TEST_ARRAY_SIZE = 200;

using namespace std;

int main(int argc, char** argv) {

    std::vector<int> v(TEST_ARRAY_SIZE, 0);

    for(size_t i = 0; i < TEST_ITERATIONS; ++i) {
#if TEST_METHOD == 1
        memset(&v[0], false, v.size() * sizeof v[0]);
#Elif TEST_METHOD == 2
        std::fill(v.begin(), v.end(), false);
   #Elif TEST_METHOD == 3
        for (std::vector<int>::iterator it=v.begin(), end=v.end(); it!=end; ++it) {
            *it = 0;
        }
   #Elif TEST_METHOD == 4
      v.assign(v.size(),false);
   #Elif TEST_METHOD == 5
      for (size_t i = 0; i < TEST_ARRAY_SIZE; i++) {
          v[i] = false;
      }
#endif
    }

    return EXIT_SUCCESS;
}

J'ai utilisé le compilateur GCC 7.2.0 sur Ubuntu 17.10. La ligne de commande pour compiler:

g++ -std=c++11 -O0 main.cpp
g++ -std=c++11 -O3 main.cpp
0
Yauhen Yakimenka