指针容器的指针别名
Pointer aliasing of pointer containers
我了解到指针别名可能会影响性能,__restrict__
属性(在GCC中,或其他实现中的等效属性(可能有助于跟踪哪些指针应该或不应该别名。同时,我还了解到GCC对valarray
的实现存储了一个__restrict__
’ed指针(https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.1/vallarray-source.html(,我认为这暗示了编译器(和负责的用户(,可以假设私有指针在valarray
方法中的任何地方都没有别名。
但是,如果我们将指向valarray
对象的指针别名,例如:
#include <valarray>
int main() {
std::valarray<double> *a = new std::valarray<double>(10);
std::valarray<double> *b = a;
return 0;
}
说a
的成员指针也有别名是有效的吗?b
的存在会损害valarray
方法在其他方面可能受益的任何优化吗?(指向优化的指针容器是不是一种糟糕的做法?(
让我们首先了解混叠是如何影响优化的。
考虑一下这个代码,
void
process_data(float *in, float *out, float gain, int nsamps)
{
int i;
for (i = 0; i < nsamps; i++) {
out[i] = in[i] * gain;
}
}
在C或C++中,参数
in
和out
指向内存中的重叠区域是合法的。。。。当编译器优化函数时,它通常不知道in
和out
是否是别名。因此必须假设通过CCD_ 13的任何存储都可以影响由CCD_,这严重限制了它对代码进行重新排序或并行化的能力(对于一些简单的情况,编译器可以分析整个程序,以确定两个指针不能是别名。但通常,编译器不可能确定两个指示器是否是别名,因此为了安全起见,它必须假设它们是别名(。
来到你的代码,
#include <valarray>
int main() {
std::valarray<double> *a = new std::valarray<double>(10);
std::valarray<double> *b = a;
return 0;
}
由于CCD_ 15和CCD_。valarray
使用的底层存储结构也会被别名化(我认为它使用了一个数组。对此不太确定(。因此,以类似于上面所示的方式使用a
和b
的代码的任何部分都不会从编译器优化(如并行化和重新排序(中受益。请注意,仅仅是b
的存在不会影响优化,而是影响您如何使用它。
学分:引用的部分和代码取自此处。这也应该是一个很好的来源,可以获得更多关于该主题的信息。
说a的成员指针也有别名是有效的吗?
是的。例如,a->[0]
和b->[0]
引用相同的对象。这就是混叠。
b的存在会损害valarray方法在其他方面可能受益的任何优化吗?
没有。
您还没有在示例代码中对b
做任何操作。假设您有一个比这个示例代码大得多的函数,它以相同的构造开始。如果该函数的前几行使用a
但从不使用b
,而其余几行则使用b
但不使用a
,则通常不会有问题。通常(不过,优化编译器确实会重新排列代码行。(
另一方面,如果混合使用a
和b
,则不会影响优化。你正在做更糟糕的事情:你正在调用未定义的行为"不要这样做"是未定义行为问题的最佳解决方案。
附录
C restrict
和gcc __restrict__
关键字对编译器或标准库的开发人员没有约束。这些关键字是对编译器/库的承诺,即受限制的数据不会与其他数据重叠。编译器/库不会检查程序员是否违反了这一承诺。如果此承诺启用某些优化,而这些优化在数据重叠时可能无效,则编译器/库可以自由应用这些优化。
这意味着restrict
(或__restrict__
(是对您的限制,而不是编译器。即使没有b
指针,也可以违反这些限制。例如,考虑
*a = a->[std::slice(a.size()-1,a.size(),-1)];
这是未定义的行为。
- C++通过别名指针以静默方式将错误的类型分配给数组元素
- 动态维度数组的 C++ 别名指针
- std::shared_ptr 使用别名构造函数,是否可以检索初始指针值?
- 类型别名允许分配任意指针,尽管 int* 是必需的
- 模板类函数指针类型别名
- 是否可以将引用类型别名与指针运算符一起使用来声明对指针的引用?
- 如何正确组合类型的别名,功能指针和模板功能
- 这是否仍然声明一种指针函数的别名?
- 将共享指针的别名构造函数与空共享指针一起使用C++
- 指针、常量和类型别名
- 在 C++ 中作为指针或别名进行内部编译的引用
- 使用指针转换来存储/转换值:我打破了严格的别名规则吗
- 如何为 noexcept 函数指针创建别名
- 取消引用类型的punned指针将打破严格的别名规则[-Wstrict aliasing]
- 从成员函数指针到另一个类型的强制转换,返回严格的别名问题
- 指针别名规则的应用(指向自身地址的指针)
- 将char[]强制转换为usingned int给出:取消引用类型的punned指针将打破严格的别名规则
- 删除别名指针
- 如何告诉C或C++编译器指针没有别名
- 指针容器的指针别名