[[carries_dependency]]属性是什么意思
What does the [[carries_dependency]] attribute mean?
有人能用普通人能理解的语言解释吗?
[[carries_dependency]]
用于允许在函数调用之间传递依赖关系。这可能允许编译器在与std::memory_order_consume
一起使用时生成更好的代码,用于在具有弱有序体系结构(如IBM的POWER体系结构)的平台上的线程之间传输值。
特别地,如果用memory_order_consume
读取的值被传递给函数,那么在没有[[carries_dependency]]
的情况下,编译器可能不得不发出内存围栏指令,以保证维持适当的内存排序语义。如果参数是用[[carries_dependency]]
注释的,那么编译器可以假设函数体将正确地携带依赖项,并且可能不再需要这个围栏。
类似地,如果函数返回用memory_order_consume
加载的值,或者从这样的值派生的值,那么在没有[[carries_dependency]]
的情况下,编译器可能需要插入fence指令,以确保支持适当的内存排序语义。有了[[carries_dependency]]
注释,这个栅栏可能不再是必要的,因为调用者现在负责维护依赖树。
例如
void print(int * val)
{
std::cout<<*val<<std::endl;
}
void print2(int * [[carries_dependency]] val)
{
std::cout<<*val<<std::endl;
}
std::atomic<int*> p;
int* local=p.load(std::memory_order_consume);
if(local)
std::cout<<*local<<std::endl; // 1
if(local)
print(local); // 2
if(local)
print2(local); // 3
在第(1)行中,依赖关系是显式的,因此编译器知道local
被取消引用,并且它必须确保保留依赖链,以避免POWER上的围栏。
在第(2)行中,print
的定义是不透明的(假设它没有内联),因此编译器必须发出一个围栏,以确保在print
中读取*p
返回正确的值。
在第(3)行,编译器可以假设,尽管print2
也是不透明的,但从参数到去引用值的依赖关系保留在指令流中,并且POWER上不需要围栏。显然,print2
的定义实际上必须保留这种依赖关系,因此属性也会影响为print2
生成的代码。
简而言之,我认为,如果有carries_dependency属性,那么为函数生成的代码应该针对某个情况进行优化,因为实际的参数确实来自另一个线程并带有依赖项。返回值也是如此。若那个种假设不成立(例如在单线程程序中),可能会出现性能不足的情况。但在相反的情况下,缺少[[carries_dependency]]可能会导致糟糕的性能。。。除了性能改变之外,没有其他影响。
例如,指针取消引用操作取决于指针之前是如何获得的,如果指针p的值来自另一个线程(通过"consume"操作),则会考虑到该另一线程先前分配给*p的值,并且该值是可见的。可能存在另一个等于p(q==p)的指针q,但由于其值不是来自该另一个线程,因此可以看出*q的值与*p不同。实际上,*q可能会引发一种"未定义的行为"(因为访问内存位置和进行赋值的另一个线程不协调)。
实际上,在某些工程案例中,内存(和大脑)的功能似乎存在一些大缺陷……>:-)
- 这个语法std::class<>{}(arg1, arg2) 在C++中是什么意思?
- 标准 N3337 5.2.10 第 7 条中的C++"类型"是什么意思?
- "类模板示例<int>;"语句对 C++11 是什么意思?
- 线应该是什么意思
- "CID"在AT+HTTPPARA= "CID" ,1中是什么意思
- 表达式"b=(b-x)&x"是什么意思?
- 这个表达是什么意思?
- 此代码验证公式是什么意思?
- 跟踪日志中的T.11803()是什么意思?
- 这个额外的关键字在这个 c++ 类声明中是什么意思?
- * 和 ** 在 C++ 函数声明中是什么意思?
- _T("xyz")是什么意思?
- #define Dbg(fmt,..) (0) 是什么意思? 警告:表达式无效
- 这行代码到底是什么意思?
- 在命名空间名称之前加上 :: 是什么意思?
- 从字符数组的元素中减去'a'是什么意思
- "friend"关键字在C++中是什么意思?
- 减法中的"0"是什么意思?
- 字符数组前面的加号是什么意思?
- 这里的字符串函数是什么意思