Каков правильный метод инициализации/загрузки векторных расширений gcc? ⇐ C++
Каков правильный метод инициализации/загрузки векторных расширений gcc?
Векторные расширения, предоставляемые GCC/Clang, — это удобный способ включить векторизацию SIMD на нескольких архитектурах (например, webassembly, Arm64, x64).
С
using v8x16u = uint8_t __attribute__((vector_size(16))); v8x16u add(v8x16u a, v8x16u b) { return a + b; } добавить v0.16b, v1.16b, v0.16b в отставку Программировать SIMD легко (даже если в некоторых случаях производительность не слишком высока).
Ни в какой документации мне не удалось найти какой предпочтительный/канонический способ инициализации этих векторов из памяти.
v8x16u load(uint8_t const *p) { v8x16u а; for (int i = 0; i < 16; i++) a = p; } работает должным образом на clang x64, clang Armv8 и немного неоптимально на GCC 7.3
ldr q0, [x0] // clangarmv8 movdqu xmm0, XMMWORD PTR [rdi] // gcc x64 7.3 movups xmm0, xmmword ptr [rdi] // clang 15.0.0 x64 sub sp, sp, #16 // GCC Arm64 7.3 лдр q0, [x0] добавить сп, сп, 16 В веб-сборке результатом является катастрофа (цикл). Развертывание загрузки работает для веб-сборки и clang, но не для GCC, который загружает 16 отдельных байтов.
v8x16u load(uint8_t const *p) { v8x16u a{p[0],p[1],p[2],p[3], р[4],р[5],р[6],р[7], р[8],р[9],р[10],р[11], р[12],р[13],р[14],р[15] }; вернуть а; } локальный.получить 0 v128.load 0:p2align=0 конечная_функция Наконец, каламбур типов компилируется, но разве это не вводит UB, а также кажется, что в clang может быть ошибка в реализации (поскольку использование vs typedef должно в этом случае AFAIK работать одинаково, сохраняя атрибуты) v8x16u load_fail(uint8_t const *p) { используя Vec = uint8_t __attribute__((vector_size(16), Align(1))); return *reinterpret_cast(p); } movaps xmm0, xmmword ptr [rdi] v8x16u load_okish(uint8_t const *p) { typedef uint8_t Vec __attribute__((vector_size(16))) __attribute__((aligned(1))); return *reinterpret_cast(p); movups xmm0, xmmword ptr [rdi] }
Векторные расширения, предоставляемые GCC/Clang, — это удобный способ включить векторизацию SIMD на нескольких архитектурах (например, webassembly, Arm64, x64).
С
using v8x16u = uint8_t __attribute__((vector_size(16))); v8x16u add(v8x16u a, v8x16u b) { return a + b; } добавить v0.16b, v1.16b, v0.16b в отставку Программировать SIMD легко (даже если в некоторых случаях производительность не слишком высока).
Ни в какой документации мне не удалось найти какой предпочтительный/канонический способ инициализации этих векторов из памяти.
v8x16u load(uint8_t const *p) { v8x16u а; for (int i = 0; i < 16; i++) a = p; } работает должным образом на clang x64, clang Armv8 и немного неоптимально на GCC 7.3
ldr q0, [x0] // clangarmv8 movdqu xmm0, XMMWORD PTR [rdi] // gcc x64 7.3 movups xmm0, xmmword ptr [rdi] // clang 15.0.0 x64 sub sp, sp, #16 // GCC Arm64 7.3 лдр q0, [x0] добавить сп, сп, 16 В веб-сборке результатом является катастрофа (цикл). Развертывание загрузки работает для веб-сборки и clang, но не для GCC, который загружает 16 отдельных байтов.
v8x16u load(uint8_t const *p) { v8x16u a{p[0],p[1],p[2],p[3], р[4],р[5],р[6],р[7], р[8],р[9],р[10],р[11], р[12],р[13],р[14],р[15] }; вернуть а; } локальный.получить 0 v128.load 0:p2align=0 конечная_функция Наконец, каламбур типов компилируется, но разве это не вводит UB, а также кажется, что в clang может быть ошибка в реализации (поскольку использование vs typedef должно в этом случае AFAIK работать одинаково, сохраняя атрибуты) v8x16u load_fail(uint8_t const *p) { используя Vec = uint8_t __attribute__((vector_size(16), Align(1))); return *reinterpret_cast(p); } movaps xmm0, xmmword ptr [rdi] v8x16u load_okish(uint8_t const *p) { typedef uint8_t Vec __attribute__((vector_size(16))) __attribute__((aligned(1))); return *reinterpret_cast(p); movups xmm0, xmmword ptr [rdi] }
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Определите размер контейнера из списка инициализации (CWG 1591). Каков правильный путь?
Anonymous » » в форуме C++ - 0 Ответы
- 66 Просмотры
-
Последнее сообщение Anonymous
-