错误、漏洞、问题 - 页 2505

 

编辑器中的一个长期存在的错误。

- 将文件保存在一个新的名称下(例如:name_v1.2)。
- 将光标放在某个变量上(或函数调用)。
- 按alt+g

- 一个旧文件被打开,编辑跳转到它(

 
Vict:

一般来说,我甚至没有想到。

这段代码有点过于复杂--我试着去找不适合缓存线的元素并直接敲击它,但是失败了(如果我想的话可能会成功,但是我觉得很无聊),而且我没有对代码做太大的改动。但这种方式更令人印象深刻--16次折叠中只有一次是针对不适合缓存行的元素进行的,但它的效果却很明显。

SZY:更客观地说,在这种情况下,通过插入两个短,而不是通过删除一个短来做RIGHT_ALIGNED(所以我们在两种情况下都会实现缓存行的两次更新)。速度的提升会比较小,但仍然是1.5倍左右。

对不起,但对准的用途在哪里?这不是这个例子的内容。

П.С.在没有评论的情况下,以粗糙的形式发布你的代码是对你的朋友的不尊重。

 

正确地指出,增加了对齐方式,以便在第三方库中使用MQL结构对象,特别是dotnet。

当dotnet库被添加到支持dotnet时,对齐被添加到包结构/类的字段中。

简而言之,它的工作原理是这样的。

对于每一种类型(char、short、int...)都有一个默认的对齐方式(分别为1、2、4字节)。
对于结构领域,将选择两种排列的最小值:默认排列和用户定义的排列(通过打包)。

同时,打包对象的大小是以这样的方式设置的,即数组中对象字段的寻址总是 "正确的"(默认的一个字节是与打包一起设置的)。
正是因为后者,人们产生了错误的印象,认为数据包对齐了结构的大小;事实并非如此,字段地址是对齐的,这就需要对齐结构的大小。



比如说

struct A pack(8)
  {
   double d;
   char   c;
  };

void OnStart()
  {
   Print(sizeof(A));
   
  }

结果16,因此,对第一个字段d的寻址总是以8个字节对齐。

 
fxsaber:

我自己的运行情况没有显示出任何明显的差异。

我改进了原来的想法(在第一个代码中,地址被错误地计算了)。如果你不介意的话,看看你的结果会很有趣。

#define  WRONG_ALIGNED
#define  CACHE_LINE_SIZE 64

struct Data {
#ifdef  WRONG_ALIGNED
   ushort pad;
#else
   uint pad;
#endif
   uint ar[CACHE_LINE_SIZE/sizeof(int)+1];
};

#import "msvcrt.dll"
  long memcpy(uint &, uint &, long);
#import
#define  getaddr(x) memcpy(x, x, 0)

void OnStart()
{
   Data data[32768];
   ZeroMemory(data);
   
   srand(GetTickCount());
   
   ulong start_time = GetMicrosecondCount();
   
   for(unsigned i = 0; i < 10000; ++ i) {
      int rndnum = rand();
      while (++rndnum < 32768) {
         int index = int(CACHE_LINE_SIZE - getaddr(data[rndnum].ar[0]) % CACHE_LINE_SIZE) / sizeof(int);
         ++ data[rndnum].ar[index];
         ++ data[rndnum].pad;
      }
   }
      
   Alert(GetMicrosecondCount() - start_time);
   
   Print(data[100].ar[0]);
   Print(data[100].pad);
}
/*
WRONG_ALIGNED:
6206397
6185472

RIGHT_ALIGNED
4089827
4003213
*/
本质上,在有/无WRONG_ALIGNED的情况下都会发生同样的事情--在每一次我们向两个相邻的缓存行写东西的时候(向pad写东西总是写到正确的地址),唯一不同的是,在有WRONG_ALIGNED的情况下(不一定),ar中的一个条目发生在uint中,它不会完全进入缓存行,我有一个大约1.5倍的稳定差异。
 
Vict:

我已经解决了原来的想法(第一个代码没有正确计算地址)。如果你不介意的话,看看你的案例的结果会很有趣。

基本上在有/无WRONG_ALIGNED的情况下都会发生同样的事情--在每一次我们写到两个相邻的缓存行(pad条目总是正确的地址),唯一不同的是,在有WRONG_ALIGNED的情况下(不总是),ar中的一个条目发生在uint中,这不会影响整个缓存行,我有一个大约1.5倍的稳定差别。

请解释一下,你想通过这句话得到什么?在前面的例子中,它是垃圾代码。

int index = int(CACHE_LINE_SIZE - getaddr(data[rndnum].ar[0]) % CACHE_LINE_SIZE) / sizeof(int);
 
Francuz:

请解释你想通过这句话得到什么?在前面的例子中,它是垃圾代码。

找到我们在当前缓存线中的位置(PAD所在的位置),并为ar[]取这样的索引,与之对应的元素在下一个缓存线中(也许元素在两个缓存线中都有WRONG_ALIGNED)。

 
Vict:

找到我们在当前缓存线中的位置(即pad所在的位置),并为ar[]取一个索引,使与之相关的元素在下一个缓存线中(也许该元素在WRONG_ALIGNED的两个缓存线中)。

现在我们谈论的是偏移。但你所展示的纯粹是一个合成的例子,在现实生活中永远不会发生。而在真实的例子中,速度的提升最多只有1%左右。你不应该为了这样一个微不足道的加速而大惊小怪。

П.С.另外,你对寄存器大小的计算也是错误的。
 
Francuz:

现在我们正在讨论流离失所问题。但你所展示的是一个纯粹的合成例子,在现实生活中永远不会遇到。在现实世界的例子中,速度的提高最多只有1%左右。你不应该对这样一个微不足道的加速度大惊小怪。

不,这是很真实的例子。只有25%的写入发生在缓存线接口处的 "问题 "地方。那是多少钱?例如,如果你有一个长的双数数组,一个缓存行只能容纳4个值,如果你不去管对齐问题(编译器也不帮你做),那么你就会有25%的问题双数位置--就像我的例子中那样。还有很多细微的差别,可以说是对准的,但我不会去说--我对这个问题不是很精通。

嗯,房子的主人。

P.S. 另外,你把寄存器的大小计算错了。
我其实根本没把他算进去 ))
 
Vict:

不,这是一个完全现实的例子。其中,只有25%的条目出现在缓存行交界处的 "问题 "地方。是很多吗?例如,如果你有一个长的双数数组,一个缓存行只容纳4个值,如果你不关心对齐问题(编译器也不为你做),那么你会得到25%的问题双数--就像我的例子一样。还有很多细微的差别,这些差别说明了对齐的问题,但我不会谈论它们--我对这个问题的了解还不够。

好吧,你是老板。

我再一次说,你被寄存器的大小所迷惑。

 
Francuz:

你又一次混淆了寄存器的大小。

说明理由