Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 页面错误maskmovdqu/_mm_maskmoveu_si128-如何避免?_Assembly_X86_Sse_Page Fault - Fatal编程技术网

Assembly 页面错误maskmovdqu/_mm_maskmoveu_si128-如何避免?

Assembly 页面错误maskmovdqu/_mm_maskmoveu_si128-如何避免?,assembly,x86,sse,page-fault,Assembly,X86,Sse,Page Fault,我有一个输出结构化数据的函数。数据是Vec4/Vec3/Vec2/float结构,因此每个结构的最大大小为16字节。现在可能会发生这样的情况,即从结构内部开始读取流。简单的解决方案:加载结构,构建存储掩码,将目标数据指针减少到调用要开始读取的结构中的字节数 假设当前项目类型为Vec2,我们在该结构中有4个字节: xmm0 = 00000000-00000000-dadadada-dadadada xmm1 = 00000000-00000000-ffffffff-00000000 result_

我有一个输出结构化数据的函数。数据是Vec4/Vec3/Vec2/float结构,因此每个结构的最大大小为16字节。现在可能会发生这样的情况,即从结构内部开始读取流。简单的解决方案:加载结构,构建存储掩码,将目标数据指针减少到调用要开始读取的结构中的字节数

假设当前项目类型为Vec2,我们在该结构中有4个字节:

xmm0 = 00000000-00000000-dadadada-dadadada
xmm1 = 00000000-00000000-ffffffff-00000000
result_data_ptr = 13450000
-> RDI = 1344fffc
maskmovdqu xmm0, xmm1
=>结果是页面错误异常


是否有任何方法可以检测是否会发生此页面错误?与AVX
vmaskmovps
或AVX512屏蔽存储不同,上一页的内存甚至不会被触摸…

maskmovdqu
不会进行故障抑制。这些方法可以解决你的问题,尽管可能仍然不是最有效的方法

,使用全零掩码(因此没有任何内容存储到内存中),与寻址内存和页面错误相关的异常仍然可能会发出信号(取决于实现)

对于非零掩码,我假设如果16个字节包含任何不可写的页面,就可以保证它不会出现页面错误。或者,有些实现甚至在某些存储发生时屏蔽也会抑制故障(未映射页面中为零,但其他地方为非零)


在真正的CPU上,它不是一个快速指令。

maskmovdqu
有时在单核奔腾4(或不是IDK)上可能很好,和/或其MMX前身在order Pentium上可能很有用。屏蔽缓存绕过存储在现代CPU上的用处要小得多,因为在现代CPU中,L3是正常的后台,并且缓存很大。也许更重要的是,在单核和内存控制器之间有更多的机器,因为即使另一个核在某个点重新加载了内存,所有东西都必须正常工作,所以部分行写入可能效率更低

如果您总共只存储8或12个字节,那么这通常是一个糟糕的选择。(基本上与不写完整行的NT存储相同)。尤其是当您使用多个窄存储来获取数据片段并将其放入一个连续流中时。我不会假设,一旦最终完成一条缓存线,多个重叠的
maskmovdqu
存储将导致整个缓存线的单个有效存储,即使掩码意味着没有字节被实际写入两次

L1d缓存非常适合在最终完成之前缓冲对缓存线的多个小写操作;使用普通商店,除非你可以做几个NT商店几乎背靠背

要存储XMM寄存器的前8个字节,请使用
movhps

写入缓存也可以进行重叠存储,如
movdqu
。因此,您可以将几个12字节的对象串接到XMM寄存器的底部(或者首先以这种方式加载它们),然后使用
movdqu
存储到
[rdi]
[rdi+12]
[rdi+24]
,等等。4字节的重叠完全可以;存储缓冲区中的合并可能会在它提交到L1d缓存之前将其吸收,或者如果没有,L1d缓存仍然非常快



在开始编写大型数组时,如果不知道对齐方式,可以对输出的前16个字节执行未对齐的
movdqu
。然后执行第一个16字节对齐的存储,可能与之重叠。如果您的总输出大小始终大于等于16字节,则此策略不需要太多分支就可以让您对大部分内容执行对齐存储。最后,您可以对最终可能未对齐的向量执行相同的操作,该向量可能与最后一个对齐的向量部分重叠。(或者如果阵列对齐,那么就没有重叠,也对齐了。
movdqu
与现代CPU上地址对齐时的速度一样快。)

maskmovdqu
与AVX
vmaskmovps
或AVX512掩蔽存储不同,它不执行故障抑制。这些方法可以解决你的问题,尽管可能仍然不是最有效的方法

,使用全零掩码(因此没有任何内容存储到内存中),与寻址内存和页面错误相关的异常仍然可能会发出信号(取决于实现)

对于非零掩码,我假设如果16个字节包含任何不可写的页面,就可以保证它不会出现页面错误。或者,有些实现甚至在某些存储发生时屏蔽也会抑制故障(未映射页面中为零,但其他地方为非零)


在真正的CPU上,它不是一个快速指令。

maskmovdqu
有时在单核奔腾4(或不是IDK)上可能很好,和/或其MMX前身在order Pentium上可能很有用。屏蔽缓存绕过存储在现代CPU上的用处要小得多,因为在现代CPU中,L3是正常的后台,并且缓存很大。也许更重要的是,在单核和内存控制器之间有更多的机器,因为即使另一个核在某个点重新加载了内存,所有东西都必须正常工作,所以部分行写入可能效率更低

如果您总共只存储8或12个字节,那么这通常是一个糟糕的选择。(基本上与不写完整行的NT存储相同)。尤其是当您使用多个窄存储来获取数据片段并将其放入一个连续流中时。我不会假设,一旦最终完成一条缓存线,多个重叠的
maskmovdqu
存储将导致整个缓存线的单个有效存储,即使掩码意味着没有字节被实际写入两次

L1d缓存非常适合在最终完成之前缓冲对缓存线的多个小写操作;使用普通商店,除非你可以做几个NT商店几乎背靠背

要存储XMM寄存器的前8个字节,请使用
movhps
.DATA
ALIGN 16
shuf_inside   byte 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0
              byte 2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,1
              byte 3,4,5,6,7,8,9,10,11,12,13,14,15,0,1,2
              byte 4,5,6,7,8,9,10,11,12,13,14,15,0,1,2,3
              byte 5,6,7,8,9,10,11,12,13,14,15,0,1,2,3,4
              byte 6,7,8,9,10,11,12,13,14,15,0,1,2,3,4,5
              byte 7,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6
              byte 8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7
              byte 9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8
              byte 10,11,12,13,14,15,0,1,2,3,4,5,6,7,8,9
              byte 11,12,13,14,15,0,1,2,3,4,5,6,7,8,9,10
              byte 12,13,14,15,0,1,2,3,4,5,6,7,8,9,10,11
              byte 13,14,15,0,1,2,3,4,5,6,7,8,9,10,11,12
              byte 14,15,0,1,2,3,4,5,6,7,8,9,10,11,12,13
              byte 15,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14
.CODE
[...]
        lea             rax,        [ shuf_inside ]
        shl             r11,        4
        pshufb          xmm2,       [ rax + r11 - 16 ]
        shr             r11,        4
        pextrw          rax,        xmm0,       6           ;reducedStrideWithPadding - i.e. size of item
        sub             rax,        r11                     ;bytes_to_write
        ;
        test            rax,        8
        jz              lessThan8
        movq            qword ptr [r10], xmm2
        psrldq          xmm2,       8
        add             r10,        8
        lessThan8:
        test            rax,        4
        jz              lessThan4
        movd            dword ptr [r10], xmm2
        psrldq          xmm2,       4
        add             r10,        4
        lessThan4:
        test            rax,        2
        jz              lessThan2
        pextrw          word ptr [r10], xmm2, 0
        psrldq          xmm2,       2
        add             r10,        2
        lessThan2:
        test            rax,        1
        jz              lessThan1
        pextrb          byte ptr [r10], xmm2, 0
        lessThan1: