En regardant la sortie de l'assembly, gcc déroule réellement cette boucle en utilisant les registres mmx pour vider en 16 octets à la fois jusqu'à ce qu'elle se rapproche de la fin. Je dirais que c'est assez rapide. La version memset passe au memset, ce qui, je suppose, est à peu près aussi rapide. J'utiliserais ta méthode.
Omnifarious
Mais, passer à memset est une instruction unique, donc son utilisation entraînera une taille binaire plus petite.
Alexander Shishenko
2
ce n'est pas exactement ce qu'OP a demandé, mais simplement réaffecter votre vecteur à un nouveau de la même taille ( v = std::vector<int>(vec_size,0)) semble légèrement plus rapide que fillsur ma machine
Yibo Yang
1
C'est la façon la plus idiomatique de le faire, plus idiomatique que d'utiliser assign.
alfC
1
l'affectation à un nouveau vecteur fait-elle une allocation de tas? puis rejeter l'allocation du vecteur existant? Je pouvais voir que c'était plus lent que memset et al
Conrad Jones
150
Comme toujours lorsque vous posez la question la plus rapide: mesurez! En utilisant les méthodes ci-dessus (sur un Mac utilisant Clang):
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
+1. Cette référence particulière n'est pas concluante, mais le point est absolument correct, vous devriez écrire un test de performance des alternatives car elles seront réellement utilisées. S'il n'y a pas de différence de performances, utilisez la source la plus simple.
Steve Jessop
3
"... pas concluant ..." IMO cette inconclusivité en soi est déjà un bon point pour faire des benchmarks, le plus souvent l'Optimizer fait déjà un très bon travail pour le genre de situations que le PO a demandé. Et je modifierais votre dernière phrase pour lire "S'il n'y a pas de différence de performance significative ..."
De plus, wow, si vous vous souciez de la vitesse sans optimisations (ce qui pourrait être plausible si vous déployez en mode `` débogage '', ce que certaines équipes font), a l' fillair terrible. Il est de deux ordres de grandeur plus lent dans ce test.
Kyle Strand
5
@KyleStrand: Ce n'est pas que le remplissage soit terrible, c'est un modèle et le code est généré avec -O0 dans votre unité de traduction. Lorsque vous utilisez memset, vous utilisez le code libc qui a été compilé avec -O3 (même lorsque vous compilez votre code avec -O0). Si vous vous souciez de la vitesse de débogage et que vous utilisez des modèles, vous devrez utiliser une instanciation de modèle explicite dans un fichier séparé que vous compilez avec -O3
L'OP voulait réinitialiser les valeurs existantes, mais votre réponse est meilleure lorsque vous souhaitez redimensionner et réinitialiser les valeurs. Merci!
15
Si c'est juste un vecteur d'entiers, j'essaierais d'abord:
Étant donné que la norme (2003 TC1) garantit qu'un vecteur std :: est contigu en mémoire, cela devrait convenir. Si votre bibliothèque c ++ n'est pas conforme au TC1 2003, ne l'utilisez pas.
Mario
2
@Mario: Je n'aurais pas posté cela à moins que cela ne soit vrai et supposé bien connu, bien sûr. :) Mais merci.
détendez-vous le
1
J'ai vérifié l'assemblage. La ::std::fillmé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.
Omnifarious
4
Vous feriez mieux d'ajouter vérifier si le vecteur est vide et ne rien faire dans ce cas. Le calcul de & buf [0] pour un vecteur vide peut générer des assertions dans le code STL.
Sergey
4
essayer
std::fill
et aussi
std::size siz = vec.size();//no memory allocating
vec.resize(0);
vec.resize(siz,0);
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.6661.045
fill 19.3571.066iterator67.3681.043
assign 17.9750.530for i 22.6101.004
Donc apparemment pour ces tailles, vector<bool>::assign()c'est plus rapide. Le code utilisé pour les tests:
Réponses:
la source
v = std::vector<int>(vec_size,0)
) semble légèrement plus rapide quefill
sur ma machineassign
.Comme toujours lorsque vous posez la question la plus rapide: mesurez! En utilisant les méthodes ci-dessus (sur un Mac utilisant Clang):
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é:
Conclusion: à utiliser
std::fill
(car, comme d'autres l'ont dit, c'est le plus idiomatique)!la source
assign
est plus lent, sauf pour les petites capacités lelibc++
. CODE coliru / collerfill
air terrible. Il est de deux ordres de grandeur plus lent dans ce test.Et la
assign
fonction membre?la source
Si c'est juste un vecteur d'entiers, j'essaierais d'abord:
Ce n'est pas très C ++, donc je suis sûr que quelqu'un fournira la bonne façon de le faire. :)
la source
::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.essayer
et aussi
la source
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):Donc apparemment pour ces tailles,
vector<bool>::assign()
c'est plus rapide. Le code utilisé pour les tests:J'ai utilisé le compilateur GCC 7.2.0 sur Ubuntu 17.10. La ligne de commande pour la compilation:
la source