Я знаю, у valarrays есть синтаксический сахар
Я должен сказать, что не думаю, что std::valarrays
имеет много синтаксического сахара. Синтаксис другой, но я бы не назвал разницу "сахар". API странный. В разделе std::valarray
s на языке программирования C ++ упоминается этот необычный API и тот факт, что, поскольку ожидается, что std::valarray
s будет высоко оптимизирован, любые сообщения об ошибках, которые вы получите при их использовании, вероятно, будут не-интуитивный.
Из любопытства около года назад я противопоставил std::valarray
против std::vector
. У меня больше нет кода или точных результатов (хотя это не должно быть трудно написать свой собственный). Использование GCC I принесло небольшой выигрыш в производительности при использовании std::valarray
для простой математики, но не для моих реализаций для расчета стандартного отклонения (и, конечно, стандартное отклонение не так сложно, насколько математика идет) Я подозреваю, что операции с каждым элементом в большом std::vector
лучше работают с кэшами, чем операции с std::valarray
с. ( NOTE , следуя советам musiphil Мне удалось получить почти одинаковую производительность от vector
и valarray
).
В конце концов, я решил использовать std::vector
, уделяя пристальное внимание таким вещам, как выделение памяти и создание временных объектов.
И std::vector
, и std::valarray
хранят данные в непрерывном блоке. Однако они получают доступ к этим данным, используя разные шаблоны, и, что более важно, API для std::valarray
поддерживает другие шаблоны доступа, чем API для std::vector
.
Для примера стандартного отклонения на конкретном этапе мне нужно было найти среднее значение для коллекции и разницу между значением каждого элемента и средним значением.
Для std::valarray
я сделал что-то вроде:
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;
Возможно, я был умнее с std::slice
или std::gslice
. Прошло уже более пяти лет.
Для std::vector
я сделал что-то вроде:
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));
Сегодня я бы, конечно, написал это по-другому. Если бы не что иное, я бы воспользовался лямбдами C ++ 11.
Очевидно, что эти два фрагмента кода делают разные вещи. Например, пример std::vector
не создает промежуточную коллекцию, как пример std::valarray
. Тем не менее, я думаю, что было бы справедливо сравнивать их, потому что различия связаны с различиями между std::vector
и std::valarray
.
Когда я писал этот ответ, я подозревал, что вычитание значений элементов из двух std::valarray
s (последняя строка в примере std::valarray
) будет менее дружественным к кэшу, чем соответствующая строка в примере std::vector
( что также является последней строкой).
Оказывается, однако, что
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;
Делает то же самое, что и пример std::vector
, и имеет почти идентичную производительность. В конце концов, вопрос в том, какой API вы предпочитаете.