Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using restrict with arrays?

Is there a way to tell a C99 compiler that the only way I am going to access given array is by using myarray[index] ? Say something like this:

int heavy_calcualtions(float* restrict range1, float* restrict range2)
{
    float __I promise I won't alias this__ tmpvalues[1000] = {0};

    ....
    heavy calculations using range1, range2 and tmpvalues;
    ....
}

By using restrict I promised that I won't alias range1 and range2 but how do I do the same thing for array declared inside my function ?

like image 568
Piotr Lopusiewicz Avatar asked Sep 26 '13 11:09

Piotr Lopusiewicz


People also ask

Why is restrict not in C++?

Because you cannot compile C++ by specifying the -std=c99 language flag, restrict is not a keyword in C++. In addition to allowing restricted pointers, you can specify restricted references, which indicate that the reference is not aliased in the local context.

What does __ restrict mean in C?

In the C programming language, restrict is a keyword, introduced by the C99 standard, that can be used in pointer declarations. By adding this type qualifier, a programmer hints to the compiler that for the lifetime of the pointer, no other pointer will be used to access the object to which it points.

How do you use restrict keywords?

When the restrict keyword is used with a pointer p, then it tells the compiler, that ptr is only way to access the object pointed by this. So compiler will not add any additional checks. If the programmer uses restrict keyword then violate the above condition, it will generate some un-defined behavior.

Does C++ have restrict?

restrict is not supported by C++. It is a C only keyword.


2 Answers

Although Jeff's answer is right, i.e., you can always make a pointer to the allocated array, the fact is that the compiler knows at compile-time that tmpvalues won't be aliased because the variable is declared as an actual array, not a pointer. The only chances to alias an array is declaring a pointer to it, so if you don't do that, there's no need to declare it as restrict. This is more evident if tmpvalues is the only variable you'll have within the function.

The problem may arise if you pass the pointer to another function, then there you should state whether the received pointer is restricted or not.

The documentation I encountered related to this topic includes the C99:

Let D be a declaration of an ordinary identifier that provides a means of designating an object P as a restrict-qualified pointer to type T.

Note that it only applies to pointers.

This other document from TI provides some performance tuning hints using the restrict keyword. In addition to all the hints, section 3.3 provides examples when it is possible to apply this type qualifier and when not. Look for the x array declaration in the middle of page 16, it states that it does not declare a pointer and thus cannot be restrict-qualified.

like image 165
Harald Avatar answered Sep 21 '22 05:09

Harald


Why can't you do the following? You are not accessing the data associated with tmpvalues via that variable, so it is valid to use a restrict pointer in the compute-intensive portion of the code.

#include <stdio.h>
#include <stdlib.h>

int heavy_calcs(int n, float* restrict range1, float* restrict range2)
{
    if (n>1000) return 1;
    float tmpvalues[1000] = {0};
    {
        float * restrict ptv = tmpvalues;
        for (int i=0; i<n; i++) {
            ptv[i] = range1[i] + range2[i];
        }
    }
    return 0;
}

int main(int argc, char * argv[])
{
    int n = (argc>1) ? atoi(argv[1]) : 1000;
    float * r1 = (float*)malloc(n*sizeof(float));
    float * r2 = (float*)malloc(n*sizeof(float));
    int rc = heavy_calcs(n,r1,r2);
    free(r1);
    free(r2);
    return rc;
}

I ran this through the Intel 15 compiler and it had no trouble vectorizing the loop. Granted, this loop is trivial to compared to what I assume yours is, so your mileage may vary.

like image 27
Jeff Hammond Avatar answered Sep 20 '22 05:09

Jeff Hammond