Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fastest way to negate a std::vector

Assume I have a std::vector of double, namely

std::vector<double> MyVec(N); 

Where N is so big that performance matters. Now assume that MyVec is a nontrivial vector (i.e. it is not a vector of zeros, but has been modified by some routine). Now, I need the negated version of the vector: I need -MyVec.

So far, I have been implementing it via

std::transform(MyVec.cbegin(),MyVec.cend(),MyVec.begin(),std::negate<double>()); 

But, really, I do not know if this is something sensible or it is just super naïve from my side.

Am I doing it correctly? Or std::transform is just a super slow routine in this case?

PS: I am using BLAS and LAPACK libraries all the time, but I have not found anything that matches this particular need. However, if there exists such a function in BLAS/LAPACK which is faster than std::transform, I would be glad to know.

like image 298
enanone Avatar asked Nov 15 '17 14:11

enanone


People also ask

How to negate a vector in Java?

The following example shows how to use this method to negate a vector. private Vector negateExample () { Vector vectorResult = new Vector (20, 30); // Make the direction of the Vector opposite but // leave the vector magnitude the same. // vectorResult is equal to (-20, -30) vectorResult.Negate (); return vectorResult; }

What's the difference between the uvector and std vector methods?

The only change in semantics of standard defined methods between the uvector and std::vector are the vector (size_t n) constructor and the resize (size_t n) methods. I found that, if you really are concerned about performance, there might be two more useful operations:

What is the use of negate function in C++?

This function is used to negate the given values i.e. to change the sign of the values. It changes the positive values to negative and vice-versa. Note: Objects of this class can be used on standard algorithms such as transform.

Can I store INT in a vector in C++?

This article is about using the std::vector class in the C++ programming language. The std::vector is a useful class for many things. However, when storing integral data types such as an int in a vector, there can be some overhead involved.


2 Answers

#include <vector> #include <algorithm> #include <functional>  void check() {     std::vector<double> MyVec(255);     std::transform(MyVec.cbegin(),MyVec.cend(),MyVec.begin(),std::negate<double>()); } 

This code on https://godbolt.org/ with copile option -O3 generate nice assembly

.L3: [...]   cmp r8, 254   je .L4   movsd xmm0, QWORD PTR [rdi+2032]   xorpd xmm0, XMMWORD PTR .LC0[rip]   movsd QWORD PTR [rdi+2032], xmm0 .L4: 

It's difficult to imagine faster. Your code is already perfect, don't try to outsmart the compiler and use clean C++ code it works almost every times.

like image 114
ColdCat Avatar answered Sep 22 '22 01:09

ColdCat


Fortunately the data in std::vector is contiguous so you can multiply by -1 using vector intrinsics (using unaligned load/stores and special handing of the possible overflow). Or use ippsMulC_64f/ippsMulC_64f_I from intel's IPP library (you'll struggle to write something faster) which will use the largest vector registers available to your platform: https://software.intel.com/en-us/ipp-dev-reference-mulc

Update: to clear up some confusion in the comments, the full version of Intel IPP is free (although you can pay for support) and comes on Linux, Windows and macOS.

like image 29
keith Avatar answered Sep 22 '22 01:09

keith