Je sais que les valarrays ont du sucre syntaxique
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 les std::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
contre std::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' utilisation std::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 std::vector
jeu mieux avec les caches que les opérations sur std::valarray
s. ( NOTE , suite aux conseils de musiphil , j'ai réussi à obtenir des performances presque identiques de vector
et valarray
).
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
et std::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 pour std::valarray
encourage des modèles d'accès différents de ceux de l'API pour std::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:
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 intelligent avec std::slice
ou std::gslice
. Cela fait plus de cinq ans maintenant.
Car std::vector
, j'ai fait quelque chose du genre:
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, 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 entre std::vector
et std::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
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 quelle API vous préférez.