Я очень люблю векторы. Они изящны и быстры. Но я знаю, что существует то, что называется valarray. Зачем мне использовать valarray вместо вектора? Я знаю, что у valarrays есть некоторый синтаксический сахар, но кроме этого, когда они полезны?
159
valarray
здесь и здесьОтветы:
Valarrays (массивы значений) предназначены для переноса части скорости Fortran в C ++. Вы не сделаете множество указателей, чтобы компилятор мог делать предположения о коде и лучше его оптимизировать. (Основная причина того, что Fortran такой быстрый, заключается в том, что нет типа указателя, поэтому не может быть псевдонима указателя.)
В Valarrays также есть классы, которые позволяют довольно легко их нарезать, хотя в этой части стандарта может потребоваться немного больше работы. Изменение их размера разрушительно, и им не хватает итераторов.
Итак, если вы работаете с числами, а удобство не так уж важно, используйте значения. В противном случае векторы намного удобнее.
источник
valarray
это своего рода сирота, которая родилась не в то время и не в том месте. Это попытка оптимизации, особенно для машин, которые использовались для тяжелой математики, когда она была написана - в частности, для векторных процессоров, таких как Crays.Для векторного процессора вы обычно хотели применить одну операцию ко всему массиву, затем применить следующую операцию ко всему массиву и так далее, пока вы не сделаете все, что вам нужно сделать.
Однако, если вы не имеете дело с довольно маленькими массивами, это плохо работает с кэшированием. На большинстве современных машин вы, как правило, предпочитаете (насколько это возможно) загружать часть массива, выполнять на нем все необходимые операции, а затем переходить к следующей части массива.
valarray
Предполагается также исключить любую возможность наложения псевдонимов, что (по крайней мере, теоретически) позволяет компилятору повысить скорость, поскольку он более свободен для хранения значений в регистрах. В действительности, однако, я совсем не уверен, что любая реальная реализация в какой-то степени использует это преимущество. Я подозреваю, что это скорее проблема типа «курица и яйцо» - без поддержки компилятора она не стала бы популярной, и пока она не популярна, никто не собирается работать над своим компилятором для ее поддержки.Есть также изумительный (буквально) массив вспомогательных классов, которые можно использовать с valarray. Вы
slice
,slice_array
,gslice
иgslice_array
играть с кускамиvalarray
, и сделать его действовать как многомерный массив. Вы также можетеmask_array
«замаскировать» операцию (например, добавить элементы от x до y, но только в местах, где z не равен нулю). Чтобы использовать их более чем тривиальноvalarray
, вам нужно многое узнать об этих вспомогательных классах, некоторые из которых довольно сложны и ни один из которых не кажется (по крайней мере, мне) хорошо документированным.Итог: хотя в нем есть моменты блеска, и он может делать некоторые вещи довольно аккуратно, есть также несколько очень веских причин, по которым он (и почти наверняка останется) неясным.
Редактировать (восемь лет спустя, в 2017 году): Некоторые из предыдущих устарели, по крайней мере, до некоторой степени. Например, Intel внедрила оптимизированную версию valarray для своего компилятора. Он использует Intel Integrated Performance Primitives (Intel IPP) для повышения производительности. Хотя точное улучшение производительности, несомненно, варьируется, быстрый тест с простым кодом показывает увеличение скорости примерно в 2: 1 по сравнению с идентичным кодом, скомпилированным со «стандартной» реализацией
valarray
.Итак, хотя я не совсем уверен, что программисты на C ++ начнут использовать
valarray
в огромных количествах, есть, по крайней мере, некоторые обстоятельства, в которых это может обеспечить повышение скорости.источник
Во время стандартизации C ++ 98, valarray был разработан, чтобы позволить какие-то быстрые математические вычисления. Тем не менее, примерно в то же время Тодд Вельдхуйзен изобрел шаблоны выражений и создал blitz ++ , и были изобретены похожие методы метаданных шаблонов, что сделало valarra-ы в значительной степени устаревшими еще до выпуска стандарта. IIRC, первоначальный разработчик (и) valarray, отказался от него на полпути к стандартизации, что (если верно) тоже не помогло.
ISTR считает, что основная причина, по которой он не был удален из стандарта, заключается в том, что никто не нашел время тщательно оценить проблему и написать предложение по ее устранению.
Имейте в виду, однако, что все это смутно помнят слухи. Возьмите это с зерном соли и надейтесь, что кто-то исправит или подтвердит это.
источник
Я должен сказать, что я не думаю
std::valarrays
, что есть много в смысле синтаксического сахара. Синтаксис другой, но я бы не назвал разницу "сахар". API странный. Разделstd::valarray
s на языке программирования C ++ упоминает этот необычный API и тот факт, что, посколькуstd::valarray
ожидается, что s будет сильно оптимизирован, любые сообщения об ошибках, которые вы получаете при их использовании, вероятно, будут не интуитивно понятными.Из любопытства около года назад я выступил
std::valarray
противstd::vector
. У меня больше нет кода или точных результатов (хотя это не должно быть трудно написать свой собственный). С помощью GCC я сделал получить немного выигрыша в производительности при использованииstd::valarray
для простой математики, но не для моих реализаций для вычисления стандартного отклонения (и, конечно же , стандартное отклонение не так сложен, насколько это математика идет).Я подозреваю, что операции с каждым элементом в целом( ПРИМЕЧАНИЕ , следуя советам от musiphil , мне удалось получить почти одинаковую производительность отstd::vector
лучше работают с кешами, чем сstd::valarray
s.vector
иvalarray
).В конце концов я решил использовать
std::vector
, уделяя пристальное внимание таким вещам, как выделение памяти и создание временных объектов.Оба
std::vector
иstd::valarray
хранят данные в непрерывном блоке. Однако они получают доступ к этим данным с использованием разных шаблонов, и, что более важно, API forstd::valarray
поощряет использование различных шаблонов доступа, чем для APIstd::vector
.Для примера стандартного отклонения на конкретном этапе мне нужно было найти среднее значение для коллекции и разницу между значением каждого элемента и средним значением.
Для
std::valarray
, я сделал что-то вроде:Возможно, я был более умным с
std::slice
илиstd::gslice
. Прошло уже более пяти лет.Для
std::vector
, я сделал что - то вдоль линий:Сегодня я бы написал это по-другому. Если бы не что иное, я бы воспользовался лямбдами C ++ 11.
Очевидно, что эти два фрагмента кода делают разные вещи. Например, в
std::vector
примере не создается промежуточная коллекция, как вstd::valarray
примере. Тем не менее, я думаю, что будет справедливо сравнить их, потому что различия связаны с различиями междуstd::vector
иstd::valarray
.Когда я писал этот ответ, я подозревал, что вычитание значений элементов из двух
std::valarray
s (последняя строка вstd::valarray
примере) будет менее дружественным к кэшу, чем соответствующая строка вstd::vector
примере (которая также является последней строкой).Оказывается, однако, что
Делает то же самое, что и в
std::vector
примере, и имеет практически идентичную производительность. В конце концов, вопрос в том, какой API вы предпочитаете.источник
std::vector
будет лучше играть с кешами, чем astd::valarray
; они оба выделяют один непрерывный блок памяти для своих элементов.valarray
приведенном выше примере вам не нужно было создаватьtemp
valarray
объект, но вы могли бы просто сделатьstd::valarray<double> differences_from_mean = original_values - mean;
, и тогда поведение кэша должно быть таким же, как вvector
примере. (Кстати, еслиmean
на самом делеint
, нетdouble
, вам может понадобитьсяstatic_cast<double>(mean)
.)valarray
. Мне нужно посмотреть, улучшает ли это производительность. Что касаетсяmean
того, чтобы бытьint
: это было ошибкой. Первоначально я написал пример с использованиемint
s, а затем понял,mean
что тогда он будет очень далек от реального среднего из-за усечения. Но я пропустил несколько необходимых изменений в моем первом раунде правок.Предполагалось, что valarray позволит немного улучшить качество векторной обработки FORTRAN на C ++. Каким-то образом необходимой поддержки компилятора никогда не было.
Книги Josuttis содержат некоторые интересные (несколько уничижительные) комментарии о valarray ( здесь и здесь ).
Однако теперь Intel, похоже, пересматривает valarray в своих последних выпусках компилятора (например, см. Слайд 9 ); это интересная разработка, учитывая, что их набор инструкций SIMD SSE с 4 путями собирается соединиться с инструкциями AVX с 8 путями и инструкциями Larrabee с 16 путями, и в интересах переносимости, вероятно, будет намного лучше кодировать с такой абстракцией, как valarray, чем (скажем) внутренности.
источник
Я нашел одно хорошее использование для valarray. Это использовать valarray так же, как массивы numpy.
Мы можем реализовать выше с Valarray.
Также нам нужен скрипт на python.
источник
Стандарт C ++ 11 гласит:
См. C ++ 11 26.6.1-2.
источник
С ним
std::valarray
вы можете использовать стандартные математические обозначения, какv1 = a*v2 + v3
из коробки. Это невозможно с векторами, если вы не определите свои собственные операторы.источник
std :: valarray предназначен для сложных числовых задач, таких как «Динамика вычислительной жидкости» или «Динамика вычислительной структуры», в которых у вас есть массивы с миллионами, иногда десятками миллионов элементов, и вы выполняете их в цикле с миллионами шагов. Возможно, сегодня std :: vector имеет сопоставимую производительность, но около 15 лет назад valarray был почти обязателен, если вы хотели написать эффективный числовой решатель.
источник