-
Notifications
You must be signed in to change notification settings - Fork 15
Const correctness in YAKL intent(in), intent(inout)
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.
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.
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.
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)
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); });
}
Assuming typedef
s 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 |