使用sse2或avx比较操作返回所有零或全部的位掩码(例如_mm_cmpge_pd返回__m128d.
我找不到avx512的等价物.比较操作似乎只返回短位掩码.语义是否发生了根本变化,或者我遗漏了什么?
假设以AVX2为目标的编译和C++内在函数,如果我每个体体计算使用17个寄存器编写一个nbody算法,那么第17个寄存器可以间接(寄存器重命名硬件)或直接(visual studio编译器,gcc编译器)映射到AVX上-512注册以减少内存依赖关闭?例如,skylake架构有1或2个AVX-512 fma单元.这个数字是否也改变了总寄存器?(具体来说,至强银4114 cpu)
如果这样可行,它是如何工作的?当所有指令都是AVX2或更低时,第一个硬件线程使用每个ZMM向量的前半部分和第二个硬件线程使用每个ZMM向量的后半部分?
编辑:如果在目标机器上进行在线编译会怎样(例如,使用OpenCL)?司机可以为我注册使用吗?
x86 cpu-architecture cpu-registers compiler-optimization avx512
我最近被介绍了向量指令(理论上)并且对如何使用它们来加速我的应用程序感到兴奋。
我想改进的一个方面是一个非常热的循环:
__declspec(noinline) void pleaseVectorize(int* arr, int* someGlobalArray, int* output)
{
for (int i = 0; i < 16; ++i)
{
auto someIndex = arr[i];
output[i] = someGlobalArray[someIndex];
}
for (int i = 0; i < 16; ++i)
{
if (output[i] == 1)
{
return i;
}
}
return -1;
}
Run Code Online (Sandbox Code Playgroud)
但是,当然,所有 3 个主要编译器(msvc、gcc、clang)都拒绝对此进行矢量化。我可以理解为什么,但我想得到确认。
如果我必须手动矢量化它,它将是:
(1) VectorLoad "arr", 这带来了 16 个 4 字节整数,让我们说到 zmm0
(2) 16个内存从zmm0[0..3]指向的地址加载到zmm1[0..3],从zmm0[4..7]指向的地址加载到zmm1[4..7]所以等等
(3)比较zmm0和zmm1
(4) 向量 popcnt 到输出中找出最高有效位并基本上除以 8 得到匹配的索引
首先,向量指令可以做这些事情吗?就像他们可以执行这种“收集”操作,即从指向 zmm0 的地址加载?
以下是 clang 生成的内容:
0000000000400530 …Run Code Online (Sandbox Code Playgroud) 给定寄存器中的数字(二进制整数),如何将其转换为十六进制ASCII数字字符串?
数字可以存储在存储器中或即时打印,但存储在存储器中并一次打印通常更有效.(您可以修改存储的循环,而不是一次打印一个循环.)
我们能否有效地处理与SIMD并行的所有半字节?(SSE2或更高版本?)
我们有一个带有 intel AVX 512 CPU 的新集群。我们对该主题进行了研究,但没有结果。我们想知道 Spark 作业是否能够在 AVX 本地运行以处理 DataFrames 对象,或者我们是否必须更改代码以允许 JVM 使用它,或者它是否完全无用。我们的 spark 应用程序是用 scala 编码的。我们的大部分工作是 DataFrames 对象处理和算法。在此先感谢您的帮助
AVX 具有将 16 位和 32 位整数插入和提取到__m256i向量中的指令:_mm256_insert_epi16, _mm256_insert_epi32, _mm256_extract_epi16, _mm256_extract_epi32。
但是,AVX-512 似乎没有等效的说明。为__m512i向量实现这些方法的适当方法是什么?IE
__m512i _mm512_insert_epi16(__m512i a, __int16 i, int index)__m512i _mm512_insert_epi32(__m512i a, __int32 i, int index)int _mm512_extract_epi16(__m512i a, int index)int _mm512_extract_epi32(__m512i a, int index)如何将掩码寄存器的所有设置位向右移动?(到底部,最不重要的位置)。
例如:
__mmask16 mask = _mm512_cmpeq_epi32_mask(vload, vlimit); // mask = 1101110111011101
Run Code Online (Sandbox Code Playgroud)
如果我们将所有设置位向右移动,我们将得到:1101110111011101 -> 0000111111111111
我怎样才能有效地实现这一目标?
您可以在下面看到我如何尝试获得相同的结果,但效率很低:
__mmask16 mask = 56797;
// mask: 1101110111011101
__m512i vbrdcast = _mm512_maskz_broadcastd_epi32(mask, _mm_set1_epi32(~0));
// vbrdcast: -1 0 -1 -1 -1 0 -1 -1 -1 0 -1 -1 -1 0 -1 -1
__m512i vcompress = _mm512_maskz_compress_epi32(mask, vbrdcast);
// vcompress:-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 0 0 0
__mmask16 right_packed_mask = _mm512_movepi32_mask(vcompress);
// right_packed_mask: 0000111111111111
Run Code Online (Sandbox Code Playgroud)
做这个的最好方式是什么?
我想探索 gcc (10.3) 的自动矢量化。我有以下简短的程序(请参阅https://godbolt.org/z/5v9a53aj6),它计算向量所有元素的总和:
#include <stdio.h>
#define LEN 1024
// -ffast-math -march=tigerlake -O3 -fno-unroll-loops
int
main()
{
float v[LEN] __attribute__ ((aligned(64)));
float s = 0;
for (unsigned int i = 0; i < LEN; i++) s += v[i];
printf("%g\n", s);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我用选项编译-ffast-math -march=tigerlake -O3 -fno-unroll-loops。由于 Tigerlake 处理器具有 avx512,我希望 gcc 自动向量化使用 zmm 寄存器,但它实际上在最内层循环中使用 ymm 寄存器(avx/avx2):
vaddps ymm0, ymm0, YMMWORD PTR [rax]
Run Code Online (Sandbox Code Playgroud)
如果我替换-march=tigerlake为-mavx512f,则使用 zmm 寄存器:
vaddps zmm0, zmm0, ZMMWORD PTR [rax]
Run Code Online (Sandbox Code Playgroud)
如果我只是指定,为什么不使用 …
_mm256_mul_ps是“乘法打包单精度(32 位)浮点元素”的 Intel 内在函数。_mm256_mul_ph是“乘法打包半精度(16 位)浮点元素”的内在函数。
我可以_mm256_mul_ps使用 using 来调用use std::arch::x86_64::*;,例如
#[inline]
fn mul(v: __m256, w: __m256) -> __m256 {
unsafe { _mm256_mul_ps(v, w) }
}
Run Code Online (Sandbox Code Playgroud)
不过,似乎很难调用_mm256_mul_ph。可以调用_mm256_mul_phRust 吗?