Sun Studio 12:C 用户指南

3.8.2 限定指针

为使编译器有效地执行循环的并行执行任务,需要确定特定左值是否指定不同的存储区域。别名是其存储区域相同的左值。由于需要分析整个程序,因此确定对象的两个指针是否为别名是一个困难而费时的过程。例如下面的函数 vsq()


示例 3–22 带两个指针的循环


void vsq(int n, double * a, double * b) {
    int i;
    for (i=0; i<n; i++) {
            b[i] = a[i] * a[i];
    }
}

如果编译器知道指针 ab 访问不同的对象,可以并行化循环的不同迭代的执行。如果通过指针 ab 访问的对象存在重叠,编译器以并行方式执行循环将会不安全。在编译时,编译器并不能通过简单地分析函数 vsq() 来获悉 ab 访问的对象是否重叠;编辑器需要分析整个程序才能获取此信息。

限定指针用来指定哪些指定不同对象的指针,以便编译器可以执行指针别名分析。以下是函数参数声明为限定指针的函数 vsq() 示例:


void vsq(int n, double * restrict a, double * restrict b)

指针 ab 声明为限定指针,因此编译器知道 ab 指向不同的存储区域。有了此别名信息,编译器就能够并行化循环。

关键字 restrict 是一个类型限定符,与 volatile 一样,但它仅限定指针类型。使用 -xc99=all(使用 -Xs 时除外)时,restrict 识别为一个关键字。在某些情况下,您可能不希望更改源代码。可以使用以下命令行选项指定将返回赋值指针函数参数视为限定指针:


-xrestrict=[func1,…,funcn]

如果指定函数列表,则指定的函数中的指针参数将被视为限定的;否则,整个 C 文件中的所有指针参数均被视为限定的。例如,-xrestrict=vsq 限定前一个有关键字 restrict 的函数 vsq() 示例中给定的指针 ab

正确使用 restrict 至关重要。如果指针被限定为限定指针而指向不同的对象,编译器会错误地并行化循环而导致不确定的行为。例如,假定函数 vsq() 的指针 ab 指向的对象重叠,如 b[i]a[i+1] 是同一对象。如果 ab 未声明为限定指针,循环将以串行方式执行。如果 ab 被错误地限定为限定指针,编译器会并行化循环的执行,但这是不安全的,因为 b[i+1] 应在 b[i] 之后进行计算。