最近读到,Fortran在数值计算方面比C/C++更快的主要原因是不存在指针别名。
显然,使用restrict
或__restrict__
关键字可以逐个案例地指示给定内存元素的无指针别名。
ICC编译器显然有一个选项-fno-alias
,它允许全局假定不存在别名。GCC上有-fno-strict-aliasing
,它仅适用于所有别名情况的子集。
是否存在GCC中的选项或在使用特定优化标志时假定不存在别名的某些情况?
最近读到,Fortran在数值计算方面比C/C++更快的主要原因是不存在指针别名。
显然,使用restrict
或__restrict__
关键字可以逐个案例地指示给定内存元素的无指针别名。
ICC编译器显然有一个选项-fno-alias
,它允许全局假定不存在别名。GCC上有-fno-strict-aliasing
,它仅适用于所有别名情况的子集。
是否存在GCC中的选项或在使用特定优化标志时假定不存在别名的某些情况?
GCC有一个选项-fstrict-aliasing
,它可以全局启用别名优化,并期望您确保没有出现非法别名。我相信此优化在-O2
和-O3
下启用。
C++有明确定义的别名规则,符合标准的代码不会与严格别名冲突。特别地,这意味着您不允许通过指向另一种类型的指针来访问一个变量:
float f;
int * p = reinterpret_cast<int*>(&f); // uh-oh
*p = 0x3FF00000; // breaks strict aliasing
这个规则的一个关键例外是,你始终可以通过char
类型的指针访问任何变量。(这对于通过IO操作进行序列化是必要的。)
别名规则无法帮助编译器知道同一类型的任何指针是否别名。考虑以下情况:
void add(float * a, float * b, float * c) { *c = *a + *b; }
编译器无法确定 c
是否指向与 a
或 b
不同的内存空间,因此必须小心处理。我认为这就是使用 restrict
的地方,它承诺 float * restrict c
意味着没有别名与 c
相关。
restrict
关键字有作用的情况实际上非常罕见,而且通常很明显在哪些情况下它是有用的。这份文档非常详细,强调了加载和存储的顺序也很重要。但正如我之前所说,你将使用这种优化的情况相当明显易见。 - Alexandre C.GCC
没有类似于Intel选项-fno-alias
的东西(基本上相当于通过restrict
注释来注释每个指针)。我真的希望它有。 - Royi