将屏蔽寄存器与 AVX-512 加载和存储一起使用时,是否会因对屏蔽元素的无效访问而引发故障?
When using a mask register with AVX-512 load and stores, is a fault raised for invalid accesses to masked out elements?
当我做一个 writemasked AVX-512 存储时,像这样:
vmovdqu8 [rsi] {k1}, zmm0
如果在 [rsi, rsi + 63]
访问的内存的某些部分未映射 但所有这些位置的写掩码为零 (即数据是由于掩码的原因实际上没有修改)。
另一种询问方式是这些 AVX-512 屏蔽存储是否具有与 AVX 中引入的 vmaskmov
类似的故障抑制能力。
如果屏蔽掉的元素接触到无效内存,则不会引发错误。
这里有一些 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 存储(无掩码)。它崩溃了,从而证明上层页面已被取消映射并且屏蔽抑制了崩溃。
当我做一个 writemasked AVX-512 存储时,像这样:
vmovdqu8 [rsi] {k1}, zmm0
如果在 [rsi, rsi + 63]
访问的内存的某些部分未映射 但所有这些位置的写掩码为零 (即数据是由于掩码的原因实际上没有修改)。
另一种询问方式是这些 AVX-512 屏蔽存储是否具有与 AVX 中引入的 vmaskmov
类似的故障抑制能力。
如果屏蔽掉的元素接触到无效内存,则不会引发错误。
这里有一些 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 存储(无掩码)。它崩溃了,从而证明上层页面已被取消映射并且屏蔽抑制了崩溃。