Quel est le moyen le plus rapide de réinitialiser chaque valeur de a std::vector<int>
à 0 et de conserver la taille initiale des vecteurs?
Une boucle for avec l'opérateur []?
Quel est le moyen le plus rapide de réinitialiser chaque valeur de a std::vector<int>
à 0 et de conserver la taille initiale des vecteurs?
Une boucle for avec l'opérateur []?
Réponses:
std::fill(v.begin(), v.end(), 0);
v = std::vector<int>(vec_size,0)
) semble légèrement plus rapide que fill
sur ma machine
assign
.
Comme toujours lorsque vous posez la question la plus rapide: mesurez! En utilisant les 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 100000 itérations sur un vecteur de 10000 pouces.
Modifier: si la modification de ces chiffres modifie de manière plausible les temps résultants, vous pouvez être certain (pas aussi bon que d'inspecter le code d'assemblage final) que le benchmark artificiel n'a pas été entièrement optimisé. Bien sûr, il est préférable de fausser les performances dans des conditions réelles. fin Modifier
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: à utiliser std::fill
(car, comme d'autres l'ont dit, c'est le plus idiomatique)!
assign
est plus lent, sauf pour les petites capacités le libc++
. CODE coliru / coller
fill
air terrible. Il est de deux ordres de grandeur plus lent dans ce test.
Et la assign
fonction membre?
some_vector.assign(some_vector.size(), 0);
Si c'est juste un vecteur d'entiers, j'essaierais d'abord:
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 le faire. :)
::std::fill
méthode se développe pour quelque chose qui est sacrément rapide, mais un peu du côté du code car il est tout en ligne. Je l'emploierais quand même parce que c'est beaucoup plus agréable à lire.
J'avais la même question mais assez courte vector<bool>
(afaik la norme permet de l'implémenter en interne différemment d'un simple 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()
c'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 la compilation:
g++ -std=c++11 -O0 main.cpp
g++ -std=c++11 -O3 main.cpp