Linux MOVDQU指令+;页面边界

Linux MOVDQU指令+;页面边界,linux,sse4,Linux,Sse4,我有一个简单的测试程序,用 跨页面边界(OS=Linux)访问数据的movdqu指令 如果映射了下面的页面,则效果很好。如果不是 然后我得到一个SIGSEGV,这可能是预期的 然而,这大大降低了未对齐负载的有用性 一点。此外,SSE4.2指令(如pcmpistri)中 允许未对齐的内存引用似乎表现出这种行为 还有 这很好——除了有许多strcmp的实现 我发现使用pcmpistri似乎无法解决这个问题 我已经设计出了一些简单的测试用例 导致这些实现失败,而每次字节的实现非常简单 strcmp实现

我有一个简单的测试程序,用 跨页面边界(OS=Linux)访问数据的movdqu指令

如果映射了下面的页面,则效果很好。如果不是 然后我得到一个SIGSEGV,这可能是预期的

然而,这大大降低了未对齐负载的有用性 一点。此外,SSE4.2指令(如pcmpistri)中 允许未对齐的内存引用似乎表现出这种行为 还有

这很好——除了有许多strcmp的实现 我发现使用pcmpistri似乎无法解决这个问题 我已经设计出了一些简单的测试用例 导致这些实现失败,而每次字节的实现非常简单 strcmp实现将在相同的数据布局下正常工作

还有一个注意事项——它显示了 64位Linux有一个似乎使用 以更安全的方式执行pcmpistri指令。实施 这个strcmp相当复杂,但似乎正在仔细尝试 以避免页面边界问题。我不确定这是否是因为 我上面描述的问题,或者它是否只是试图 通过对齐数据获得更好的性能

不管怎样,我的问题主要是——我在哪里可以找到更多 关于这个问题?我输入了“movdqu越界”和 我能想到的谷歌的每一个变体,但都没有遇到 任何特别有用的东西。如果有人能告诉我更多的信息
对此,我们将不胜感激。

首先,任何试图访问未映射地址的算法都会导致SegFault。如果非AVX代码流使用4字节加载访问页面的最后一个字节和碰巧未映射的“下一页”的前3个字节,则也会导致SegFault。不我认为“问题”在于AVX(1/2/3)寄存器比“典型”寄存器大得多,以至于那些不安全(但侥幸逃脱)的算法如果简单地扩展到更大的寄存器,就会被捕获

对齐负载(MOVDQA)永远不会出现此问题,因为它们不会跨越其自身大小或更大的任何边界。未对齐的负载可能会有此问题(如您所注意到的),而且“经常”会有此问题。这是因为指令被定义为加载目标寄存器的完整大小。您需要非常仔细地查看指令定义中的操作数类型。不管你对多少数据感兴趣。指令被定义做什么很重要

然而

AVX1(Sandybridge)添加了一个“屏蔽移动”功能,该功能比movdqa或movdqu速度慢,但不会(在体系结构上)访问未映射的页面,只要该页面中的访问部分未启用屏蔽。这是为了解决这个问题。一般来说,向前看,加载/存储的屏蔽部分(参见AVX512)似乎也不会导致IA上的访问冲突


(这是一个关于PCMPxSTRx行为的问题。也许你可以给你的“字符串”对象添加15字节的填充?

我在写一个库时遇到了一个类似的问题,来自一个非常有用的贡献者

该思想的核心是将16字节的读取与字符串的结尾对齐,然后在开头处理剩余的字节。这是因为字符串的结尾必须位于可访问页面中,并且可以保证16字节截断的起始地址也必须位于可访问页面中

由于我们从不读取超过字符串的内容,因此我们可能无法进入受保护的页面


为了处理初始字节集,我选择使用
PCMPxSTRM
函数,这些函数返回匹配字节的位掩码。然后,只需移动结果以忽略在字符串真正开头之前出现的任何掩码位。

实现可能会这样做,以避免跨越页面边界对性能造成影响。英特尔处理器(不确定最新的处理器)在跨页面边界的错误对齐访问方面有着令人震惊的性能历史。但是页面错误的问题应该是无关紧要的。我对这个问题的答案很好奇。《英特尔优化手册》(第10.3.6节)仅指出,“未对齐的128位SIMD内存访问可以跨页面边界获取数据,因为系统软件以页面粒度管理内存访问权限。”。也许可以尝试在其他操作系统上复制相同的bug?或者更确切地说,该操作系统将响应页面错误并将其分页-应用程序看不见(除了巨大的性能损失)。或者,如果未分配应用程序,则使其崩溃。在这种情况下,访问未分配的内存是标准的。到底是什么问题<如果您传递一个未终止的字符串并让它运行到未映射的页面中,则code>strcmp也将生成
SIGSEG
。这正是访问未映射页面所做的。作为对最后一条评论的响应。。我仔细构造了一个测试,其中字符串位于4K页面的偏移量4090处,值为“test”和“\0”字节。以下内存页未映射。当我将strcmp与该字符串一起用作参数时,一切正常。当我尝试可比较的pcmpistri指令时,将尝试加载整个16字节的块——跨入下一页,触发SIGSEGV。这就是限制pcmpistri对我有用性的原因,也是为什么我想知道一些使用它的strcmp实现。