错误、漏洞、问题 - 页 2500

 
Vict:

你在一个错误的地方挖掘。 你根本不需要对齐,处理器需要它,而不是为了在两条高速缓存线上得到一些int。

没有,处理器缓存根本没有加载数据预取,不同的缓存级别根本没有加载过渡预测,pack()根本无法到达那里(进入缓存),任何算术操作(2个int的加法)而不是在1或3个(假设的)时钟周期上执行,都会导致数据排列分析,等等。

在物理层面上,它应该是这样工作的:编译器在其中创建了可执行代码,是的,会有pack(),但是当从RAM加载数据时,它将只读取int数据,数据段指针将立即被移到pack()字节(而不是int字节)。


虽然我可能是错的,但现在所有的进程(包括处理器本身)都被虚拟化和优化了--这是我的推理,因为我在学习时读了关于Pentium-1的书--....。当年太贵了 ))))

 
Igor Makanu:

没有,处理器缓存根本没有加载数据预取,不同的缓存级别根本没有加载过渡预测,pack()根本无法到达那里(进入缓存),任何算术操作(2个int的加法)而不是在1或3个(假设的)时钟周期上执行,都会导致数据排列分析,等等。

在物理层面上,它应该是这样工作的:编译器在其中创建了可执行代码,是的,会有pack(),但是当从RAM中加载数据时,只会读取int数据,数据段指针会立即移动到pack()字节(而不是int字节)。

我并没有说pack()是CPU的服务信息,我的意思是所有这些与CPU而不是与程序员的利益相一致的舞蹈。当然,它是由编译器通过在结构中插入一个空白来实现的。

 
Alexey Viktorov:

也就是说,在MQL5中根本就没有对齐。

它已经存在很长时间了。

 
Vict:

你在错误的地方挖掘,对齐根本不适合你。

好吧,虽然我可以想到的一个真正的用途是在多线程环境中,安排数据,使不同的核心不写到同一个缓存行,但由于不断的缓存同步,这确实会减慢性能。嗯,那里也有很多细微的差别,比如CPU类型。

 
fxsaber:

它已经存在很长时间了。

你还记得是在哪里写的吗?

 
fxsaber:

那么我恐怕就失去了对准的意义

在字节中尝试了一下,看看对齐的效果如何。

#property strict

const uint FFFF=0xFFFFFFFF;
//+------------------------------------------------------------------+
struct A pack(4)
  {
   ushort            j;
  };
//+------------------------------------------------------------------+
struct B pack(8)
  {
   ushort            j;
  };
//+------------------------------------------------------------------+
union UnionCheckByte
  {
   uint              byte_2x4[2];
   A                 a;
   B                 b;
  };
//+------------------------------------------------------------------+
void OnStart()
  {
   UnionCheckByte tst;
   tst.byte_2x4[0]=FFFF;   tst.byte_2x4[1]=FFFF;   // заполним память 0xFFFFFFFF FFFFFFFF
   Print("0xFFFFFFFF FFFFFFFF = ",tst.byte_2x4[0],",",tst.byte_2x4[1]);   // проверим
   
   
   
   tst.byte_2x4[0]=FFFF;   tst.byte_2x4[1]=FFFF;   // заполним память 0xFFFFFFFF FFFFFFFF
   tst.a.j=0;
   Print("A.  = ",tst.byte_2x4[0],",",tst.byte_2x4[1]);   // проверим



   tst.byte_2x4[0]=FFFF;   tst.byte_2x4[1]=FFFF;   // заполним память 0xFFFFFFFF FFFFFFFF
   tst.b.j=0;
   Print("B.  = ",tst.byte_2x4[0],",",tst.byte_2x4[1]);   // проверим
  }
//+------------------------------------------------------------------+

2019.07.07 17:51:30.601 tst (EURUSD,H1) 0xFFFFFFFFFF FFFFFFFFFF = 4294967295,4294967295

2019.07.07 17:51:30.601 tst (EURUSD,H1) A. = 4294901760,4294967295

2019.07.07 17:51:30.601 tst (EURUSD,H1) B. = 4294901760,4294967295




要么是我还没睡醒,要么是pack(4)/pack(8)对齐方式不起作用,我明确向编译器指定了结构 A和B的尺寸


即便如此。

 ZeroMemory(tst.a);   //tst.a.j=0;
没有变化
 
Alexey Viktorov:

你还记得它是在哪里写的吗?

我不记得文档中是否有这个内容。

 
Igor Makanu:

试图看看在字节中的对齐情况。

要么是我还没睡醒,要么是pack(4)/pack(8)对齐方式不起作用,我毫不含糊地告诉编译器结构 A和B的大小

这个讨论 就是这样开始的。事实证明,情况并非如此。

嗯,这个样本毕竟是不正确的。在清零ushort-field时,额外的字节根本不需要改变。


ZeroMemory很可能是由sizeof引导的,而它在这两种情况下都是2,是出于自身的某种原因。

 
fxsaber:

所以这就是这次讨论的开始。 事实证明,根本就不是这样的。

1.那么,这个例子毕竟是不正确的。通过将ushort-field归零,额外的字节根本不需要改变。


2.ZeroMemory必须由sizeof引导,而在这两种情况下,由于某种原因,它是双倍的。


1.是的,我同意

2.ZeroMemory应该只是为我调零内存


我不认为在纯粹的MQL中使用pack()有任何意义,你最多可以使用.dll来处理数据,但它应该是有效的,这是开发人员说的。

 
Igor Makanu:

2.ZeroMemory正是我所需要的,以重置内存。

它确实如此。

struct A pack(4)
{
  short j;
  char i;
};

union U
{
  A a;
  uchar Bytes[sizeof(A)];
  
  U() { ArrayInitialize(this.Bytes, (char)0xFF); }
};

void OnStart()
{
  U u;
  
  ArrayPrint(u.Bytes); // 255 255 255 255
  
  ZeroMemory(u.a);
  ArrayPrint(u.Bytes); // 0 0 0 0
}