Eu sei que os valarrays têm um pouco de açúcar sintático
Eu tenho que dizer que acho que não std::valarraystem muito açúcar sintático. A sintaxe é diferente, mas eu não chamaria a diferença de "açúcar". A API é estranha. A seção std::valarrays na linguagem de programação C ++ menciona essa API incomum e o fato de que, desdestd::valarray se espera que seja altamente otimizado, todas as mensagens de erro que você recebe ao usá-las provavelmente não serão intuitivas.
Por curiosidade, cerca de um ano atrás eu opus std::valarraycontra std::vector. Não tenho mais o código ou os resultados precisos (embora não deva ser difícil escrever o seu próprio). Usando GCC I fez ficar um pouco benefício de desempenho quando se utiliza std::valarraypara a matemática simples, mas não para os meus implementações para calcular o desvio padrão (e, claro, o desvio padrão não é tão complexo, na medida em matemática vai). Eu suspeito que as operações em cada item em uma grande std::vectorpeça melhor com caches do que as operações em std::valarrays. ( NOTA , seguindo os conselhos de musiphil , eu consegui um desempenho quase idêntico de vectore valarray).
No final, decidi usar std::vectorprestando muita atenção a coisas como alocação de memória e criação temporária de objetos.
Ambos std::vectore std::valarrayarmazenam os dados em um bloco contíguo. No entanto, eles acessam esses dados usando padrões diferentes e, mais importante, a API std::valarrayincentiva diferentes padrões de acesso que a API std::vector.
Para o exemplo de desvio padrão, em uma etapa específica, eu precisava encontrar a média da coleção e a diferença entre o valor de cada elemento e a média.
Para o std::valarray, eu fiz algo como:
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;
Eu posso ter sido mais inteligente com std::sliceou std::gslice. Já faz mais de cinco anos.
Pois std::vector, eu fiz algo como:
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));
Hoje certamente escreveria isso de maneira diferente. Se nada mais, eu aproveitaria o C ++ 11 lambdas.
É óbvio que esses dois trechos de código fazem coisas diferentes. Por um lado, o std::vectorexemplo não cria uma coleção intermediária como o std::valarrayexemplo. No entanto, acho justo compará-los porque as diferenças estão ligadas às diferenças entre std::vectore std::valarray.
Quando escrevi esta resposta, suspeitei que subtrair o valor dos elementos de dois std::valarrays (última linha no std::valarrayexemplo) seria menos compatível com o cache do que a linha correspondente no std::vectorexemplo (que também é a última linha).
Acontece, no entanto, 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;
Faz a mesma coisa que o std::vectorexemplo e tem desempenho quase idêntico. No final, a questão é qual API você prefere.