Prevention of duplication of internal objects of the object

I have a function signature similar to this

void Mutliply(const MatrixMN& a, const MatrixMN& b, MatrixMN& out); 

Internally, the matrix class has float* data; which represents the components of mxn . I would like to tell the compiler that a and b do not have aliases, so it does not do tons of boot storage.

How would I do that? I know that I can pass pointers to a function and mark pointers with __restrict (in MSVC), but I would like to save the object idiom passed by reference, where the object contains pointers to memory.

I also know that __restrict does not work with object references.

+6
source share
4 answers

Write a non-exported (file- static , private ) multiplication function that takes float* arguments, mark the arguments with restrict . Make a Multiply call to this function.

+1
source

Depending on how the optimizer works, assert(&in1 != &out && &in2 != &out) at the top may do the trick. You can also get rid of the out parameter and trust the optimizer to get rid of extra copies (provided, of course, that this is a clean parameter, of course). If the code is a candidate for embedding the compiler, he can see that nothing is an alias on his own. If restrict doesn’t really work with reference parameters, you can get an additional level for calling the function and pass all three functions to the second, which take pointers that are correctly bounded. Hopefully this will be for you.

+2
source

Since you think __restrict pointers are convenient for you, I would use what you know, but you can still wrap it and provide an interface using the links:

 void Multiply(const MatrixMN& a, const MatrixMN& b, MatrixMN& out) { if (&a == &b || &a == &out || &b == &out) { // indicate precondition violation however you like assert(!"precondition violated"); abort(); // assert isn't always executed } else { DoMultiply(&a, &b, &out); } } void DoMultiply(MatrixMN const * __restrict a, MatrixMN const * __restrict b, MatrixMN * __restrict out) { //... } 

Make the pointer version “non-public”, for example, place it in the “details” namespace by providing it with an internal link (not applicable in this particular case) or by giving it a special name. You can even use local variables instead of parameters and put the function body in "else", but I find the cleaning tool described above.

+1
source

How about the macro shell having an __restrict effect at compile time : (below pseudo code, not checked):

 #define Multiply(A,B,C) Multiply_restrict(&A, &B, &C) 

Now the intermediate method is defined as

 inline void Multiply_restrict(const MatrixMN* __restrict pA, const MatrixMN* __restrict pB, MatrixMN* __restrict pC) { Multiply_(*pA, *pB, *pC); } 

And finally, just add _ after the original Multiply :

 void Mutliply_(const MatrixMN& a, const MatrixMN& b, MatrixMN& out); 

Thus, the final effect will be the same as you call:

 Multiply(x, y, answer); 
-1
source

Source: https://habr.com/ru/post/890105/


All Articles