Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent two object internals from aliasing

I have a function signature similiar to this

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

Internally the matrix class has a float* data; that represents the m x n components. I'd like to tell the compiler that a and b do not alias the out matrix so it doesn't do a ton of load-stores.

How would I go about doing that? I know I could pass in pointers to the function signature and mark the pointers with __restrict(in MSVC) but I'd like to keep the idiom of object passed by reference where the object contains pointers to memory.

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

like image 662
coderdave Avatar asked Jun 09 '11 02:06

coderdave


3 Answers

Depending on how the optimizer works, an assert(&in1 != &out && &in2 != &out) at the top may do the trick. You could also get rid of the out parameter, and trust the optimizer to get rid of the superfluous copies (assuming it is a pure out parameter, of course). If the code is a candidate for inlining the compiler may see nothing is aliased on it's own. If restrict really doesn't work on reference parameters, you can have an extra level to the function call, and pass all three to a second function that accepts pointers properly restricted. Hopefully, that one would get inlined for you.

like image 191
Dennis Zickefoose Avatar answered Oct 01 '22 02:10

Dennis Zickefoose


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

like image 23
n. 1.8e9-where's-my-share m. Avatar answered Sep 29 '22 02:09

n. 1.8e9-where's-my-share m.


Since you seem to be comfortable with __restrict pointers, I would use what you know, but you can still wrap it and provide an interface using references:

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", such as placing it in a "details" namespace, giving it internal linkage (not applicable in this exact case), or giving it a special name. You could even use local variables instead of parameters and put the function body within the "else", but I find the above cleaner.

like image 28
Fred Nurk Avatar answered Sep 29 '22 02:09

Fred Nurk