什么是未对齐的临时文件?

时间:2018-10-28 09:18:52

标签: c++

answer在谈论const T&时提到,由于“临时人员错位”,它会变慢。什么是未对齐的临时文件,我在代码中会在哪里遇到?

答案指出:

  

由于临时人员的位置不一致和间接调用的成本,采取const T&的速度可能会变慢。

然后有两个评论:

  

即使没有由于未对齐而导致的性能损失,仅将引用实现为指针这一事实也要求将值存储在主存储器中,该值可以介于1(L1缓存)和10(页面错误)之间。比通过寄存器慢几个数量级。

这不能解释什么是未对齐的临时文件。指针可以指向未对齐的地址,但这不能解释什么是未对齐的临时地址。下一条评论未解决:

  

为什么临时人员会不结盟?除非您误入未定义的行为,否则C ++中的所有对象都是按照定义对齐的。

2 个答案:

答案 0 :(得分:2)

在严格的C ++中,无法对齐对象[basic.align]/1

  

对象类型具有对齐要求([basic.fundamental],[basic.compound]),这些条件对可以分配该类型的对象的地址施加了限制。

无论是否临时,都不能使对象未对齐。就是说,未对齐的对象用于低级代码,但此类代码涉及非标准的c ++代码(例如,参见Linux-kernel-doc/unaligned-memory-access.txt)。您可以尝试通过以下方式将未对齐(不存在)的对象传递给函数:

void f(const int& x);
void g(long x){
   f(*reinterpret_cast<const int*>(reinterpret_cast<const unsigned char*>(&x)+1));
   }

在这样的代码中,这将导致未定义的行为,编码人员清楚地表明我们没有遵循该标准,传递给int的{​​{1}}对象不存在。因此,我们在另一个领域中,也许在这个领域中,可以将这个f对象称为临时对象。这样的代码确实存在。

第一个谈论缓存的注释未满足需要,以便理解调用约定的知识(如何在汇编级传递参数)。在所有ABI上,引用都是通过指向所引用对象的指针传递的。因此,必须将引用的对象复制到内存中。最初位于寄存器中的int的参数x将被复制到内存中的某个存储位置,然后将其传递给g。在gcc生成的f的AMD64汇编代码下面:

g

传递给//the argument x of g is in register rdi. g(long): sub rsp, 24 mov QWORD PTR [rsp+8], rdi //x is copied on to the stack lea rdi, [rsp+9] //the misaligned pointer is stored in //the first argument of f call f(int const&) add rsp, 24 ret 的参数保存在内存中,当后者的值将被访问时,该访问可能会产生高速缓存未命中,并且与正确对齐的情况相比,高速缓存未命中可能会更多,因为int对象可能散布在两条缓存行(请参阅f)。因此,如果对象可以通过其他方式传递到寄存器中(也就是说,如果对象是可微复制的并且足够小-窗口x86_64上为8字节,对于x86_64则为Sys V abi,​​则按引用传递参数不是最佳选择)。如果物体未对准,这是最糟糕的情况。

rsp+9以值作为参数时,会产生更好的代码:

f

生成的程序集是完美的:

void f(int x);
void g(long x){
   f(*reinterpret_cast<const int*>(reinterpret_cast<const unsigned char*>(&x)+1));
   }

答案 1 :(得分:1)

没有理由期望临时人员会错位。担心由于间接引用导致引用效率不及值的担心是正确的,也许有时您甚至可能找到对未对齐值的引用,但临时对齐的可能性极小。

注意:在发布此问题之前,网络搜索“ c ++“临时对齐的””只有一个结果,从而导致404错误页面。