-->

Using restrict with arrays?

2019-04-20 04:54发布

问题:

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 ?

回答1:

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.



回答2:

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.