I like vectors a lot. They're nifty and fast. But I know this thing called a valarray exists. Why would I use a valarray instead of a vector? I know valarrays have some syntactic sugar, but other than that, when are they useful?
相关问题
- Sorting 3 numbers without branching [closed]
- How to compile C++ code in GDB?
- Why does const allow implicit conversion of refere
- thread_local variables initialization
- What uses more memory in c++? An 2 ints or 2 funct
相关文章
- Class layout in C++: Why are members sometimes ord
- How to mock methods return object with deleted cop
- Which is the best way to multiply a large and spar
- C++ default constructor does not initialize pointe
- Selecting only the first few characters in a strin
- What exactly do pointers store? (C++)
- Converting glm::lookat matrix to quaternion and ba
- What is the correct way to declare and use a FILE
valarray is kind of an orphan that was born in the wrong place at the wrong time. It's an attempt at optimization, fairly specifically for the machines that were used for heavy-duty math when it was written -- specifically, vector processors like the Crays.
For a vector processor, what you generally wanted to do was apply a single operation to an entire array, then apply the next operation to the entire array, and so on until you'd done everything you needed to do.
Unless you're dealing with fairly small arrays, however, that tends to work poorly with caching. On most modern machines, what you'd generally prefer (to the extent possible) would be to load part of the array, do all the operations on it you're going to, then move on to the next part of the array.
valarray is also supposed to eliminate any possibility of aliasing, which (at least theoretically) lets the compiler improve speed because it's more free to store values in registers. In reality, however, I'm not at all sure that any real implementation takes advantage of this to any significant degree. I suspect it's rather a chicken-and-egg sort of problem -- without compiler support it didn't become popular, and as long as it's not popular, nobody's going to go to the trouble of working on their compiler to support it.
There's also a bewildering (literally) array of ancillary classes to use with valarray. You get slice, slice_array, gslice and gslice_array to play with pieces of a valarray, and make it act like a multi-dimensional array. You also get mask_array to "mask" an operation (e.g. add items in x to y, but only at the positions where z is non-zero). To make more than trivial use of valarray, you have to learn a lot about these ancillary classes, some of which are pretty complex and none of which seems (at least to me) very well documented.
Bottom line: while it has moments of brilliance, and can do some things pretty neatly, there are also some very good reasons that it is (and will almost certainly remain) obscure.
Edit (eight years later, in 2017): Some of the preceding has become obsolete to at least some degree. For one example, Intel has implemented an optimized version of valarray for their compiler. It uses the Intel Integrated Performance Primitives (Intel IPP) to improve performance. Although the exact performance improvement undoubtedly varies, a quick test with simple code shows around a 2:1 improvement in speed, compared to identical code compiled with the "standard" implementation of
valarray
.So, while I'm not entirely convinced that C++ programmers will be starting to use
valarray
in huge numbers, there are least some circumstances in which it can provide a speed improvement.I have to say that I don't think
std::valarrays
have much in way of syntactic sugar. The syntax is different, but I wouldn't call the difference "sugar." The API is weird. The section onstd::valarray
s in The C++ Programming Language mentions this unusual API and the fact that, sincestd::valarray
s are expected to be highly optimized, any error messages you get while using them will probably be non-intuitive.Out of curiosity, about a year ago I pitted
std::valarray
againststd::vector
. I no longer have the code or the precise results (although it shouldn't be hard to write your own). Using GCC I did get a little performance benefit when usingstd::valarray
for simple math, but not for my implementations to calculate standard deviation (and, of course, standard deviation isn't that complex, as far as math goes).I suspect that operations on each item in a large(NOTE, following advice from musiphil, I've managed to get almost identical performance fromstd::vector
play better with caches than operations onstd::valarray
s.vector
andvalarray
).In the end, I decided to use
std::vector
while paying close attention to things like memory allocation and temporary object creation.Both
std::vector
andstd::valarray
store the data in a contiguous block. However, they access that data using different patterns, and more importantly, the API forstd::valarray
encourages different access patterns than the API forstd::vector
.For the standard deviation example, at a particular step I needed to find the collection's mean and the difference between each element's value and the mean.
For the
std::valarray
, I did something like:I may have been more clever with
std::slice
orstd::gslice
. It's been over five years now.For
std::vector
, I did something along the lines of:Today I would certainly write that differently. If nothing else, I would take advantage of C++11 lambdas.
It's obvious that these two snippets of code do different things. For one, the
std::vector
example doesn't make an intermediate collection like thestd::valarray
example does. However, I think it's fair to compare them because the differences are tied to the differences betweenstd::vector
andstd::valarray
.When I wrote this answer, I suspected that subtracting the value of elements from two
std::valarray
s (last line in thestd::valarray
example) would be less cache-friendly than the corresponding line in thestd::vector
example (which happens to also be the last line).It turns out, however, that
Does the same thing as the
std::vector
example, and has almost identical performance. In the end, the question is which API you prefer.During the standardization of C++98, valarray was designed to allow some sort of fast mathematical computations. However, around that time Todd Veldhuizen invented expression templates and created blitz++, and similar template-meta techniques were invented, which made valarrays pretty much obsolete before the standard was even released. IIRC, the original proposer(s) of valarray abandoned it halfway into the standardization, which (if true) didn't help it either.
ISTR that the main reason it wasn't removed from the standard is that nobody took the time to evaluate the issue thoroughly and write a proposal to remove it.
Please keep in mind, however, that all this is vaguely remembered hearsay. Take this with a grain of salt and hope someone corrects or confirms this.
valarray was supposed to let some FORTRAN vector-processing goodness rub off on C++. Somehow the necessary compiler support never really happened.
The Josuttis books contains some interesting (somewhat disparaging) commentary on valarray (here and here).
However, Intel now seem to be revisiting valarray in their recent compiler releases (e.g see slide 9); this is an interesting development given that their 4-way SIMD SSE instruction set is about to be joined by 8-way AVX and 16-way Larrabee instructions and in the interests of portability it'll likely be much better to code with an abstraction like valarray than (say) intrinsics.
I found one good usage for valarray. It's to use valarray just like numpy arrays.
We can implement above with valarray.
Also, we need python script.
The C++11 standard says:
See C++11 26.6.1-2.