Skip to content

Const correctness in YAKL intent(in), intent(inout)

Matt Norman edited this page Jan 12, 2022 · 2 revisions

If you're a C++ programmer, const correctness is likely always on your mind (well, it should be anyway). While it can improve performance in some cases, in my experience, performance isn't typically affected that greatly. What const correctness will do, however, is save you from a ton of potential bugs in your code.

If you're a Fortran programmer, this is closely related to having intent(in), intent(out), or intent(inout) in your routine interfaces. It might surprise you to know that Fortran compilers typically treat intent(out) and intent(inout) identically. Code up some examples, and see for yourself. My hunch is that this is because intent(in) is the same things as const in C++, and intent(inout) is the same thing as not having const in C++.

Const correctness is the notion that you want to ensure you know what's read-only and what's being written to at any point in a code. It reaches further into classes to ensure you know what class methods are altering the class data members.

This idea gets a little hairy with YAKL (or any portable C++ implementation for that matter). The reason is the shallow copy / move semantics of the Array classes.

When to use a const modifier on the Array object

As long as you are not overwriting an Array object (this is not talking about writing to the data pointed to by an Array object but rather overwriting the object itself -- this will be explained better in the example below), it should include the const modifier. This means that most of the time, you should have a const modifier to all Array objects being passed as function parameters. If you add const and weren't supposed to, then the compiler will throw an error at compile time.

When to use an Array of a const data type: intent(in)

If you are not writing to the data pointed to by an Array object (this corresponds to intent(in) in Fortran codes), then it needs to be accepted in the function arguments as an Array object templated on a const data type. In these cases, it must be passed by value and not by reference because, typically, the Array object being passed is not templated on a const data type.

When to pass the Array as is: intent(inout) and intent(out)

If you are writing to the data pointed to by an Array object, then the object can be passed by reference as is (typically with a const modifier per two paragraphs above)

Examples:

typedef float real;
typedef Array<real      ,1,memDevice,styleC> real1d;
typedef Array<real const,1,memDevice,styleC> realConst1d;

// In this case, you cannot const-qualify "arr" because the object is being overwritten
// This is one of the only cases in which you cannot const qualify an Array object in a function parameter
void allocate( real1d &arr ) {
  arr = Array<int,1,memDevice,styleC>("arr",1024);
}

// The arrays are read-only in this function, so it needs to be an Array of const data type
// Array objects of const data type must typically be passed by value, not by reference
// Since objects passed by value cannot be altered, there is not need to const-qualify the object
real1d sum(realConst1d a, realConst1d b) {
  real1d c("sum",size(a));
  parallel_for( size(a) , YAKL_LAMBDA (int i) { c(i) = a(i) + b(i); });
  return c;
}

// This is the same as the previous function, but the result is passed back by parameter reference
// c's data is being written to, so it is passed as a const reference
void sum(realConst1d a, realConst1d b, real1d const &c) {
  parallel_for( size(a) , YAKL_LAMBDA (int i) { c(i) = a(i) + b(i); });
}

Summary

Assuming typedefs below, knowing it's the same for any style, memory space, or data type:

typedef float real;
typedef Array<real      ,2,memDevice,styleC> real2d;
typedef Array<real const,2,memDevice,styleC> realConst2d;
Fortran intent C++ function parameter form
intent(in) realConst2d array
intent(inout) / intent(out) (Array object is not overwritten) real2d const &array
intent(inout) / intent(out) (Array object is overwritten) real2d &array
Clone this wiki locally