最近读到 fortran 在数值计算中比 c/c++ 快的主要原因是因为没有指针别名。
显然,使用restrict
or__restrict__
关键字允许根据具体情况来指示给定内存元素不存在指针别名。
icc 编译器显然有一个选项-fno-alias
,它允许全局假设不存在别名。在 gcc 上有-fno-strict-aliasing
,它仅适用于所有别名情况的子集。
在使用某些优化标志时,gcc 中是否存在选项,或者是否存在不假定别名的情况?
最近读到 fortran 在数值计算中比 c/c++ 快的主要原因是因为没有指针别名。
显然,使用restrict
or__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
orb
并且必须小心。我认为这是有所作为的地方restrict
,本质上是通过承诺这float * restrict c
意味着没有人别名c
。