当使用带有 AVX-512 加载和存储的屏蔽寄存器时,是不是会因对屏蔽元素的无效访问而引发错误?

Posted

技术标签:

【中文标题】当使用带有 AVX-512 加载和存储的屏蔽寄存器时,是不是会因对屏蔽元素的无效访问而引发错误?【英文标题】:When using a mask register with AVX-512 load and stores, is a fault raised for invalid accesses to masked out elements?当使用带有 AVX-512 加载和存储的屏蔽寄存器时,是否会因对屏蔽元素的无效访问而引发错误? 【发布时间】:2019-06-27 01:43:47 【问题描述】:

当我执行 writemasked AVX-512 存储时,如下所示:

vmovdqu8 [rsi] k1, zmm0

如果在[rsi, rsi + 63] 访问的内存的某些部分没有被映射但是所有这些位置的写掩码为零(即,由于掩码,数据实际上没有被修改,那么指令会出错吗? )。

另一种询问方式是,这些 AVX-512 掩码存储是否具有与 AVX 中引入的vmaskmov 类似的故障抑制能力。

【问题讨论】:

是的,现在查找第 2 卷手册参考。 2.7 EVEX 编码指令的异常分类。它没有特别区分存储和负载,但我认为他们会说如果存储没有vmaskmovps 那样抑制故障。他们确实使用术语“内存故障抑制”。 (还有 FPU 故障抑制)。他们确实将 NT 存储列为 not 抑制故障(我猜即使所有掩码位都已清除)。 我 95% 确信被屏蔽的元素不会出错。我已经看到英特尔编译器以这种方式剥离循环,我自己也做过很多次,从未遇到任何问题。但诚然,我自己从未用 mmap 等进行过实际测试。 OTOH,我确实从某个地方(我忘了在哪里)读到,对被屏蔽元素的无效访问仍然会带来缓存未命中 + TLB 未命中的性能损失。 这样的幻灯片让我只相信而不是实际测试它:images.anandtech.com/doci/11550/basin_falls_june_6-page-011.jpg @Mysticial - 是的,我在搜索中遇到了类似的幻灯片(尽管可能是相同的事实)。有点奇怪,我们在手册中找不到任何完全确定的东西,尽管彼得发现的东西非常接近。 【参考方案1】:

如果被屏蔽的元素触及无效内存,则不会引发故障。


这里有一些 Windows 测试代码来证明屏蔽确实可以抑制内存故障。

#include <immintrin.h>
#include <iostream>
#include <Windows.h>
using namespace std; 


int main()
    const size_t PAGE = 4096;

    //  Map 2 pages.
    char* ptr = (char*)VirtualAlloc(
        nullptr, 2*PAGE,
        MEM_COMMIT,
        PAGE_READWRITE
    );

    //  Store 64 bytes across page boundary.
    cout << "Store across page boundary." << endl;
    _mm512_storeu_si512(ptr + PAGE - 32, _mm512_set1_epi8(-1));

    //  Unmap top page.
    cout << "Unmap top page." << endl;
    VirtualFree(ptr + PAGE, PAGE, MEM_DECOMMIT);

    //  Write on boundary masking out the part that touches the top (unmapped page).
    //  Does not crash because bad accesses are masked out.
    cout << "Store across page boundary, but mask out bytes that are on unmapped page." << endl;
    _mm512_mask_storeu_epi8(ptr + PAGE - 32, 0x00000000ffffffff, _mm512_set1_epi8(-1));

    //  Store 64 bytes across page boundary.
    //  Crashes because of bad access.
    cout << "Store across page boundary." << endl;
    _mm512_storeu_si512(ptr + PAGE - 32, _mm512_set1_epi8(-1));

    cout << "Release bottom page." << endl;
    VirtualFree(ptr, 0, MEM_RELEASE);

    system("pause");

输出:

Store across page boundary.
Unmap top page.
Store across page boundary, but mask out bytes that are on unmapped page.
Store across page boundary.
**Access violation**

这个测试的工作原理如下:

    映射 2 个相邻页面。 跨页面边界执行 AVX512 存储,以证明两个页面都已映射。 取消映射上部页面。 执行相同的 AVX512 存储,但屏蔽上页上的字节。它不会崩溃。 重复第一个 AVX512 存储(不加掩码)。它崩溃了,从而证明上面的页面已经被取消映射,并且屏蔽抑制了崩溃。

【讨论】:

同一演示文稿中的另一张幻灯片 (gcc.gnu.org/wiki/…) 提到使用内存源操作数 进行错误抑制(因为屏蔽是每个 dst 位置,而不是源代码)。但这些幻灯片没有明确提到商店。无论如何,感谢您对此进行测试以确认我们所有人的想法。 另外值得一提的是,在相信这个测试之前先看看程序集,因为编译器有足够的空间来打败它。虽然 MSVC 和 Intel 编译器都不是这种情况,但编译器可以优化其中一些死存储或对屏蔽存储进行强度降低(因为高 32 字节都是非活动的)。

以上是关于当使用带有 AVX-512 加载和存储的屏蔽寄存器时,是不是会因对屏蔽元素的无效访问而引发错误?的主要内容,如果未能解决你的问题,请参考以下文章

使用内在函数将双 SSE2/AVX/AVX512 存储为浮点数的最佳方法

AVX2 和 AVX-512 有啥区别?

有没有办法用avx2自动替换avx512?

使用 AVX512 或 AVX2 计算所有压缩 32 位整数之和的最快方法

动态确定恶意 AVX-512 指令的执行位置

如何编译 TensorFlow 二进制文件以使用 AVX2、AVX512F、FMA?