【发布时间】:2014-03-10 00:07:06
【问题描述】:
我有一个简单的测试程序,它加载一个 xmm 寄存器 movdqu 指令跨页边界访问数据(OS = Linux)。
如果映射了以下页面,则可以正常工作。如果不是 映射然后我得到一个 SIGSEGV,这可能是预期的。
但是,这大大降低了未对齐负载的有用性 一点点。另外 SSE4.2 指令(如 pcmpistri) 允许未对齐的内存引用似乎表现出这种行为 也是。
没关系——除了有很多 strcmp 的实现 使用我发现似乎无法解决此问题的 pcmpistri 完全没有——而且我已经能够设计出微不足道的测试用例 导致这些实现失败,而每次一个字节微不足道 strcmp 实现可以在相同的数据布局下正常工作。
还有一点需要注意——它似乎是 GNU C 库实现 64 位 Linux 有一个 __strcmp_sse42 变体,它似乎使用 pcmpistri 指令以更安全的方式进行。实施 这个 strcmp 相当复杂,但似乎在仔细尝试 以避免页面边界问题。我不确定这是否是由于 我在上面描述的问题,或者它是否只是尝试的副作用 通过对齐数据获得更好的性能。
无论如何,我的问题主要是 -- 我在哪里可以找到更多信息 关于这个问题?我输入了“movdqu 跨越页面边界”和 我能想到的谷歌的每一个变种,但还没有遇到 任何特别有用的东西。如果有人可以向我指出更多信息 对此将不胜感激。
【问题讨论】:
-
__strcmp_sse42实现可能是为了避免跨越页面边界对性能造成的影响。英特尔处理器(不确定最新的处理器)在跨页面边界的未对齐访问方面有着令人震惊的性能历史。页面错误问题应该无关紧要。 -
我很好奇这个问题的答案。英特尔优化手册(第 10.3.6 节)仅说“未对齐的 128 位 SIMD 内存访问可以跨页边界获取数据,因为系统软件以页粒度管理内存访问权限。”。也许尝试在其他操作系统上重现相同的错误?
-
或者更确切地说,操作系统将响应页面错误并将其分页 - 对应用程序不可见(除了对性能造成巨大影响)。或者如果未分配应用程序则崩溃。在这种情况下,访问未分配内存是标准 UB。
-
到底是什么问题?
strcmp也将生成SIGSEG如果您传递未终止的字符串并让它运行到非映射页面。这正是访问非映射页面所做的事情。 -
作为对最后一条评论的回应。我仔细构建了一个测试,其中字符串位于 4K 页面的偏移量 4090 处,值为“test”和“\0”字节。以下内存页面未映射。当我将该字符串作为参数使用 strcmp 时,一切正常。当我尝试类似的 pcmpistri 指令时,会尝试加载整个 16 字节块——进入下一页,触发 SIGSEGV。这就是限制 pcmpistri 对我有用的原因,也是为什么我想知道我发现的一些使用它的 strcmp 实现。