Donc, j’aime beaucoup vecteurs. Ils sont astucieux et rapide. Mais je sais pas ce qu’on appelé un valarray existe. Pourquoi devrais-je utiliser un valarray plutôt que d’un vecteur ? Je sais que valarrays ont des quantités de sucre syntaxique, mais autre que cela, quand sont-ils utiles ?
Réponses
Trop de publicités?valarray est une orpheline qui est né dans le mauvais endroit, au mauvais moment. C'est une tentative d'optimisation, assez spécifiquement pour les machines qui ont été utilisés pour un devoir de maths quand elle a été écrite -- en particulier, le vecteur des processeurs comme les Crays.
Pour un vecteur de processeur, ce que vous généralement voulais faire était d'appliquer une seule opération à l'ensemble d'un tableau, puis appliquer l'opération suivante à l'ensemble de la matrice, et ainsi de suite jusqu'à ce que vous aviez fait tout le nécessaire à faire.
Sauf si vous avez affaire avec assez de petits tableaux, cependant, qui a tendance à mal fonctionner avec la mise en cache. Sur la plupart des machines modernes, ce que vous souhaitez préfèrent généralement (dans la mesure du possible) serait à la charge de la partie de la matrice, faire toutes les opérations que vous allez, puis passer à la partie suivante de la matrice.
valarray est également censé éliminer toute possibilité d'aliasing, ce qui (au moins théoriquement) permet au compilateur d'améliorer la vitesse, car il est plus libre pour stocker les valeurs dans les registres. En réalité, cependant, je ne suis pas du tout sûr que la réelle mise en œuvre prend avantage de ce à un degré significatif. Je soupçonne que c'est plutôt un poulet et des œufs genre de problème, sans prise en charge du compilateur, il n'est pas devenu populaire, et tant qu'il n'est pas populaire, personne ne va prendre la peine de travailler sur leur compilateur pour le soutenir.
Il y a aussi une incroyable (littéralement) tableau des auxiliaires des classes à utiliser avec valarray. Vous obtenez tranche, slice_array, gslice et gslice_array à jouer avec les pièces d'un valarray, et de le faire agir comme un tableau multidimensionnel. Vous bénéficiez également de mask_array de "masque", une opération (par exemple, ajouter des éléments de x à y, mais seulement dans les positions où z est non nul). Pour faire plus qu'anecdotique utilisation de valarray, vous avez beaucoup à apprendre à propos de ces accessoires de classes, dont certaines sont assez complexes et aucun ne semble (au moins pour moi) très bien documenté.
Bottom line: si elle a des moments de génie, et peut faire des choses assez proprement, il y a aussi quelques très bonnes raisons qu'il est (et sera presque certainement rester obscur.
Valarrays (valeur les tableaux) sont destinés à apporter de la vitesse de Fortran pour C++. Vous ne voudriez pas faire un valarray de pointeurs de sorte que le compilateur peut faire des hypothèses sur le code et l'optimiser au mieux. (La raison principale que le Fortran est tellement rapide qu'il n'existe aucun type de pointeur donc il peut y avoir aucun pointeur aliasing.)
Valarrays aussi avoir des classes qui vous permettent de les couper en tranches dans une assez moyen facile bien que cette partie de la norme pourrait utiliser un peu plus de travail. Leur taille est destructeur et qu'il y manque des itérateurs.
Alors, si c'est de numéros que vous travaillez avec et la commodité n'est pas le plus important, utilisez valarrays. Sinon, les vecteurs sont juste beaucoup plus pratique.
Au cours de la normalisation du C++98, valarray a été conçu pour permettre une sorte de rapide des calculs mathématiques. Cependant, autour de ce temps, Todd Veldhuizen inventé l'expression des modèles et créé blitz++, et similaire au modèle de méta techniques ont été inventé, ce qui fait valarrays assez bien obsolètes avant même que le standard a même été publié. IIRC, l'auteur de la proposition initiale(s) de valarray abandonné à mi-chemin de la normalisation, ce qui (si vrai) n'a pas aidé non plus.
ISTR la principale raison pour laquelle il n'était pas retiré de la norme, c'est que personne n'a pris le temps d'évaluer la question à fond et rédiger une proposition visant à supprimer.
Veuillez garder à l'esprit, cependant, que tout cela est reconnu par ouï-dire. Prenez cela avec un grain de sel et j'espère que quelqu'un corrige ou confirme ce.
Je sais valarrays ont certaines sucre syntaxique
Je dois dire que je ne pense pas qu'
std::valarrays
ont beaucoup de sucre syntaxique. La syntaxe est différente, mais je ne qualifierais pas la différence "sucre". L'API est bizarre. La section sur l'std::valarray
s dans Le Langage de Programmation C++ mentionne cette inhabituelle de l'API et le fait que, depuisstd::valarray
s devraient être hautement optimisé, les messages d'erreur que vous obtenez lors de leur utilisation sera probablement non intuitive.Par curiosité, il ya environ un an j'ai piqué
std::valarray
contrestd::vector
. Je n'ai plus le code ou la précision des résultats (bien que ça ne devrait pas être difficile à écrire votre propre). À l'aide de GCC je ne obtenir un peu d'avantage de performances lors de l'utilisation d'std::valarray
pour les mathématiques simples, mais pas pour mon implémentations pour calculer l'écart-type (et, bien sûr, l'écart-type n'est pas complexe, dans la mesure du calcul).Je soupçonne que les opérations sur chaque élément d'un grand(REMARQUE, en suivant les conseils de musiphil, j'ai réussi à obtenir des performances presque identiques à partir d'std::vector
mieux jouer avec les caches que les opérations surstd::valarray
s.vector
etvalarray
).En fin de compte, j'ai décidé d'utiliser
std::vector
tout en prêtant une attention à des choses comme l'allocation de la mémoire et de la création d'un objet temporaire.Les deux
std::vector
etstd::valarray
stocker les données dans un bloc contigu. Cependant, ils ont accès à ces données à l'aide de différents modèles, et plus important encore, l'API pourstd::valarray
encourage les profils d'accès différents que l'API pourstd::vector
.Pour l'écart-type exemple, à une étape particulière il me fallait trouver la collection est moyenne et la différence entre chaque valeur de l'élément et de le dire.
Pour l'
std::valarray
, j'ai fait quelque chose comme:std::valarray<double> original_values = ... // obviously I put something here double mean = original_values.sum() / original_values.size(); std::valarray<double> temp(mean, original_values.size()); std::valarray<double> differences_from_mean = original_values - temp;
J'ai peut-être été plus à l'aise avec les
std::slice
oustd::gslice
. Cela fait plus de cinq ans maintenant.Pour
std::vector
, j'ai fait quelque chose le long des lignes de:std::vector<double> original_values = ... // obviously, I put something here double mean = std::accumulate(original_values.begin(), original_values.end(), 0.0) / original_values.size(); std::vector<double> differences_from_mean; differences_from_mean.reserve(original_values.size()); std::transform(original_values.begin(), original_values.end(), std::back_inserter(differences_from_mean), std::bind1st(std::minus<double>(), mean));
Aujourd'hui, je serais certainement écrire différemment. Si rien d'autre, je pourrais profiter de C++11 lambdas.
Il est évident que ces deux bouts de code faire des choses différentes. Pour l'un, l'
std::vector
exemple ne pas en faire une collecte intermédiaires comme l'std::valarray
exemple. Cependant, je pense qu'il est juste de comparer car les différences sont liées aux différences entrestd::vector
etstd::valarray
.Quand j'ai écrit cette réponse, je me doutais bien que la soustraction de la valeur des éléments de deux
std::valarray
s (dernière ligne de l'std::valarray
exemple) serait moins le cache de l'environnement que la ligne correspondante dans l'std::vector
exemple (qui est aussi la dernière ligne).Il s'avère, cependant, que
std::valarray<double> original_values = ... // obviously I put something here double mean = original_values.sum() / original_values.size(); std::valarray<double> differences_from_mean = original_values - mean;
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 qui de l'API que vous préférez.
valarray était censée permettre à certains FORTRAN vecteur de traitement de la bonté déteindre sur le C++. En quelque sorte, la nécessaire prise en charge du compilateur jamais vraiment arrivé.
Le Josuttis livres contient des intéressants (un peu désobligeantes) commentaire sur valarray (ici et ici).
Cependant, Intel semblent maintenant être revoir valarray dans leur récent compilateur versions (e.g voir la diapositive 9); c'est un développement intéressant étant donné que 4 SIMD jeu d'instructions SSE est sur le point d'être rejoint par 8-way AVX et 16 voies Larrabee instructions et dans l'intérêt de la portabilité, il sera probablement beaucoup mieux de code avec une abstraction comme valarray que (dire) intrinsèques.