J'aime beaucoup les vecteurs. Ils sont astucieux et rapides. Mais je sais que cette chose appelée valarray existe. Pourquoi utiliser un valarray au lieu d'un vecteur? Je sais que les valarrays contiennent du sucre syntaxique, mais à part ça, quand sont-ils utiles?
159
valarray
ici et iciRéponses:
Les Valarrays (tableaux de valeurs) sont destinés à apporter une partie de la vitesse de Fortran au C ++. Vous ne feriez pas un tableau de valeurs de pointeurs pour que le compilateur puisse faire des hypothèses sur le code et l'optimiser mieux. (La raison principale pour laquelle Fortran est si rapide est qu'il n'y a pas de type de pointeur donc il ne peut y avoir d'alias de pointeur.)
Les Valarrays ont également des classes qui vous permettent de les découper de manière assez simple, bien que cette partie de la norme puisse nécessiter un peu plus de travail. Leur redimensionnement est destructeur et ils manquent d'itérateurs.
Donc, si ce sont des nombres avec lesquels vous travaillez et que la commodité n'est pas si importante, utilisez les valarres. Sinon, les vecteurs sont beaucoup plus pratiques.
la source
valarray
est une sorte d'orphelin qui est né au mauvais endroit au mauvais moment. C'est une tentative d'optimisation, assez spécifiquement pour les machines qui ont été utilisées pour les mathématiques lourdes quand il a été écrit - en particulier, les processeurs vectoriels comme les Crays.Pour un processeur vectoriel, ce que vous vouliez généralement faire était d'appliquer une seule opération à un tableau entier, puis d'appliquer l'opération suivante à l'ensemble du tableau, et ainsi de suite jusqu'à ce que vous ayez fait tout ce que vous deviez faire.
Sauf si vous avez affaire à des tableaux assez petits, cependant, cela a tendance à mal fonctionner avec la mise en cache. Sur la plupart des machines modernes, ce que vous préférez généralement (dans la mesure du possible) serait de charger une partie du tableau, d'effectuer toutes les opérations que vous allez effectuer dessus, puis de passer à la partie suivante du tableau.
valarray
est également censé éliminer toute possibilité d'aliasing, ce qui (du moins en théorie) permet au compilateur d'améliorer la vitesse car il est plus libre de stocker des valeurs dans des registres. En réalité, cependant, je ne suis pas du tout sûr qu'une mise en œuvre réelle en profite de manière significative. Je soupçonne que c'est plutôt un problème de poule et d'oeuf - sans le support du compilateur, il n'est pas devenu populaire, et tant que ce n'est pas populaire, personne ne va se donner la peine de travailler sur son compilateur pour le supporter.Il existe également un tableau déroutant (littéralement) de classes auxiliaires à utiliser avec valarray. Vous obtenez
slice
,slice_array
,gslice
etgslice_array
de jouer avec des morceaux d'unvalarray
, et le faire agir comme un tableau multidimensionnel. Vous pouvez égalementmask_array
"masquer" une opération (par exemple, ajouter des éléments de x à y, mais uniquement aux positions où z est différent de zéro). Pour faire un usage plus que trivial devalarray
, vous devez en apprendre beaucoup sur ces classes auxiliaires, dont certaines sont assez complexes et dont aucune ne semble (du moins à moi) très bien documentée.Conclusion: bien qu'il ait des moments de brillance et qu'il puisse faire certaines choses assez bien, il y a aussi de très bonnes raisons pour lesquelles il est (et restera presque certainement) obscur.
Edit (huit ans plus tard, en 2017): Certains des précédents sont devenus obsolètes au moins dans une certaine mesure. Pour un exemple, Intel a implémenté une version optimisée de valarray pour son compilateur. Il utilise les primitives Intel Integrated Performance (Intel IPP) pour améliorer les performances. Bien que l'amélioration exacte des performances varie sans aucun doute, un test rapide avec du code simple montre une amélioration de la vitesse d'environ 2: 1, par rapport à un code identique compilé avec l'implémentation "standard" de
valarray
.Donc, bien que je ne sois pas entièrement convaincu que les programmeurs C ++ commenceront à l'utiliser
valarray
en grand nombre, il y a moins de circonstances dans lesquelles cela peut améliorer la vitesse.la source
Lors de la standardisation de C ++ 98, valarray a été conçu pour permettre une sorte de calculs mathématiques rapides. Cependant, à cette époque, Todd Veldhuizen a inventé des modèles d'expression et créé blitz ++ , et des techniques de modèle-méta similaires ont été inventées, ce qui a rendu les valarrays à peu près obsolètes avant même la publication de la norme. IIRC, le (s) proposant (s) original (s) de valarray l'a abandonné à mi-chemin de la normalisation, ce qui (si c'est vrai) ne l'a pas aidé non plus.
ISTR que la principale raison pour laquelle il n'a pas été supprimé de la norme est que personne n'a pris le temps d'évaluer le problème en profondeur et d'écrire une proposition pour le supprimer.
Veuillez garder à l'esprit, cependant, que tout cela est un ouï-dire dont on se souvient vaguement. Prenez ceci avec un grain de sel et espérez que quelqu'un corrige ou confirme cela.
la source
Je dois dire que je ne pense pas
std::valarrays
avoir beaucoup de sucre syntaxique. La syntaxe est différente, mais je n'appellerais pas la différence «sucre». L'API est bizarre. La section sur lesstd::valarray
s du langage de programmation C ++ mentionne cette API inhabituelle et le fait que, depuisstd::valarray
s sont censés être hautement optimisés, tous les messages d'erreur que vous obtenez en les utilisant seront probablement non intuitifs.Par curiosité, il y a environ un an , je dénoyautées
std::valarray
contrestd::vector
. Je n'ai plus le code ni les résultats précis (même s'il ne devrait pas être difficile d'écrire le vôtre). En utilisant GCC , je l'ai fait obtenir un peu d' avantages de performances lors de l' utilisationstd::valarray
des mathématiques simples, mais pas pour mes mises en œuvre pour calculer l' écart - type (et, bien sûr, l' écart - type est pas complexe, dans la mesure où les mathématiques va).Je soupçonne que les opérations sur chaque élément d'un grand( NOTE , suite aux conseils de musiphil , j'ai réussi à obtenir des performances presque identiques destd::vector
jeu mieux avec les caches que les opérations surstd::valarray
s.vector
etvalarray
).Au final, j'ai décidé de l'utiliser
std::vector
en prêtant une attention particulière à des choses comme l'allocation de mémoire et la création d'objets temporaires.Les deux
std::vector
etstd::valarray
stockent les données dans un bloc contigu. Cependant, ils accèdent à ces données en utilisant différents modèles et, plus important encore, l'API pourstd::valarray
encourage des modèles d'accès différents de ceux de l'API pourstd::vector
.Pour l'exemple de l'écart type, à une étape particulière, j'ai dû trouver la moyenne de la collection et la différence entre la valeur de chaque élément et la moyenne.
Pour le
std::valarray
, j'ai fait quelque chose comme:J'ai peut-être été plus intelligent avec
std::slice
oustd::gslice
. Cela fait plus de cinq ans maintenant.Car
std::vector
, j'ai fait quelque chose du genre:Aujourd'hui, j'écrirais certainement cela différemment. Si rien d'autre, je profiterais des lambdas C ++ 11.
Il est évident que ces deux extraits de code font des choses différentes. D'une part, l'
std::vector
exemple ne crée pas de collection intermédiaire comme le fait l'std::valarray
exemple. Cependant, je pense qu'il est juste de les comparer car les différences sont liées aux différences entrestd::vector
etstd::valarray
.Quand j'ai écrit cette réponse, je soupçonnais que soustraire la valeur des éléments de deux
std::valarray
s (dernière ligne de l'std::valarray
exemple) serait moins compatible avec le cache que la ligne correspondante dans l'std::vector
exemple (qui se trouve être également la dernière ligne).Il s'avère cependant que
Fait la même chose que l'
std::vector
exemple et a des performances presque identiques. En fin de compte, la question est de savoir quelle API vous préférez.la source
std::vector
jouerait mieux avec les caches que astd::valarray
; ils allouent tous deux un seul bloc de mémoire contigu pour leurs éléments.valarray
exemple ci-dessus, vous n'avez pas eu à construire d'temp
valarray
objet, mais vous auriez pu simplement le fairestd::valarray<double> differences_from_mean = original_values - mean;
, puis le comportement du cache devrait être similaire à celui de l'vector
exemple. (Au fait, simean
c'est vraimentint
, pasdouble
, vous pourriez avoir besoinstatic_cast<double>(mean)
.)valarray
. J'aurai besoin de voir si cela améliore les performances. Quant à l'mean
êtreint
: c'était une erreur. J'ai initialement écrit l'exemple en utilisantint
s, puis j'ai réalisé que lemean
serait alors très loin de la vraie moyenne à cause de la troncature. Mais j'ai manqué quelques changements nécessaires lors de ma première série de modifications.valarray était censé laisser une certaine bonté de traitement vectoriel FORTRAN déteindre sur C ++. D'une manière ou d'une autre, le support nécessaire du compilateur n'a jamais vraiment eu lieu.
Les livres de Josuttis contiennent des commentaires intéressants (quelque peu désobligeants) sur le valarray ( ici et ici ).
Cependant, Intel semble maintenant revoir valarray dans ses récentes versions de compilateur (par exemple, voir la diapositive 9 ); c'est un développement intéressant étant donné que leur jeu d'instructions SIMD SSE 4 voies est sur le point d'être rejoint par des instructions AVX 8 voies et Larrabee 16 voies et dans l'intérêt de la portabilité, il sera probablement beaucoup mieux de coder avec une abstraction comme valarray que (disons) intrinsèques.
la source
J'ai trouvé un bon usage pour valarray. Il s'agit d'utiliser valarray comme les tableaux numpy.
Nous pouvons implémenter ci-dessus avec valarray.
De plus, nous avons besoin d'un script python.
la source
La norme C ++ 11 dit:
Voir C ++ 11 26.6.1-2.
la source
Avec,
std::valarray
vous pouvez utiliser la notation mathématique standard comme prête à l'emploiv1 = a*v2 + v3
. Cela n'est possible avec les vecteurs que si vous définissez vos propres opérateurs.la source
std :: valarray est destiné aux tâches numériques lourdes, telles que Computational Fluid Dynamics ou Computational Structure Dynamics, dans lesquelles vous avez des tableaux avec des millions, parfois des dizaines de millions d'éléments, et vous les parcourez dans une boucle avec également des millions de pas de temps. Peut-être qu'aujourd'hui std :: vector a une performance comparable mais, il y a 15 ans, valarray était presque obligatoire si vous vouliez écrire un solveur numérique efficace.
la source