我正在研究并行处理算法以提高处理速度。\n我想测试Agner Fog\ 的矢量类库 VCL。
\n\n我想知道如何选择不同的向量类,例如Vec16c(SSE2 指令集)和Vec32c(AVX 指令集)。
我使用的是 Intel\xc2\xae Atom\xe2\x84\xa2 x5-Z8350 处理器,根据规格,它支持 SSE4.2 指令集。
\n\n如何在硬件支持方面有效选择向量类?\n对于我的处理器,我可以使用 AVX 指令集推荐的 Vec32c 吗?
\n我想知道编译器如何处理内部函数。
如果使用 SSE2 Intrinsics (Using #include <emmintrin.h>) 并使用-mavx标志进行编译。编译器会生成什么?它会生成 AVX 或 SSE 代码吗?
如果使用 AVX2 Intrinsics (Using #include <immintrin.h>) 并使用-msse2标志进行编译。编译器会生成什么?它会生成 SSE Only 或 AVX 代码吗?
编译器如何处理内部函数?
如果使用 Intrinsics,它是否可以帮助编译器理解循环中的依赖关系以实现更好的矢量化?
例如,这里发生了什么 - https://godbolt.org/z/Y4J5OA(或https://godbolt.org/z/LZOJ2K)?
查看全部 3 个窗格。
我正在尝试构建具有不同 CPU 功能(SSE4 和 AVX2)的相同功能的各种版本。
我正在使用 SSE Intrinsics 编写相同的版本,并且使用 AVX Intrinsics 编写一次。
假设他们的名字MyFunSSE()是 和MyFunAVX()。两者都在同一个文件中。
如何让编译器(相同的方法适用于 MSVC、GCC 和 ICC)仅使用各自的函数来构建它们?
我编写了一些用于处理单精度浮点计算 SIMD 内在函数的优化。
有时,双精度指令比任何单精度指令pd更容易满足我的要求。ps
示例1:
我有指针float prt * ,它指向浮点数块: f0 f1 f2 f3 等。
我想用 [ f0, f1, f0, f1, f0, f1, f0, f1 ] 加载 __m256 值。我没有找到__m256数据类型的 64 位广播。我可以_mm256_broadcast_sd在花车上使用吗?
float* ptr = ...; // pointer to some memory chunk aligned to 4 bytes
__m256 vat = _mm256_castpd_ps( _mm256_broadcast_sd( ( double* )ptr ) );
Run Code Online (Sandbox Code Playgroud)
示例2:
我有 __m256 值 [f0, f1, f2, f3, f4, f5, f6, f7]。我可以使用像 _mm256_srl_epi32 这样的移位指令,它以 __m256i 值作为参数来使用我的 __m256 值进行操作吗? …
__m256i我正在寻找使用 AVX 将压缩的 32 位整数除以二(也称为右移一位)的最快方法。我无法访问 AVX2。据我所知,我的选择是:
如果我需要使用 SSE2,我会欣赏最好的 SSE2 实现。如果是 2),我想知道要使用的内在函数,以及是否有更优化的实现来专门除以 2。谢谢!
ALIGNTO(16) uint8_t noise_frame_flags[16] = { 0 };
// Code detects noise and sets noise_frame_flags omitted
__m128i xmm0 = _mm_load_si128((__m128i*)noise_frame_flags);
bool isNoiseToCancel = _mm_extract_epi64(xmm0, 0) | _mm_extract_epi64(xmm0, 1);
if (isNoiseToCancel)
cancelNoises(audiobuffer, nAudioChannels, audio_samples, noise_frame_flags);
Run Code Online (Sandbox Code Playgroud)
这是我在 Linux 上的 AV Capture 工具的代码片段。这里的noise_frame_flags是16通道音频的标志数组。对于每个通道,相应的字节可以是 0 或 1。1 表示该通道有一些噪声需要消除。例如,如果noise_frame_flags[0] == 1,则意味着设置了第一个通道噪声标志(通过省略的代码)。
即使设置了一个“标志”,我也需要调用cancelNoises. 这段代码在这方面似乎工作得很好。正如您所看到的,我曾经_mm_load_si128加载正确对齐的整个标志数组,然后加载两个_mm_extract_epi64来提取“标志”。我的问题是有更好的方法来做到这一点(也许使用流行计数)?
注意:ALIGNTO(16)是一个宏扩展以纠正 GCC 等效项,但外观更好。
我有以下代码片段(可以在此处找到要点),其中我尝试对 4 个 int32_t 负值和 4 个 int16_t 值(将符号扩展为 int32_t)之间进行求和。
extern exit
global _start
section .data
a: dd -76, -84, -84, -132
b: dw 406, 406, 406, 406
section .text
_start:
movdqa xmm0, [a]
pmovsxwd xmm2, [b]
paddq xmm0, xmm2
;Expected: 330, 322, 322, 274
;Results: 330, 323, 322, 275
call exit
Run Code Online (Sandbox Code Playgroud)
然而,当通过我的调试器时,我无法理解为什么输出结果与预期结果不同。任何想法 ?
我的输入是 2 个复数浮点向量。两个向量不交错:
VecAReal = Are0, Are1, Are2,...Are[N-1]
VecAImag = Aim0, Aim1, Aim2,...Aim[N-1]
VecBReal = Bre0, Bre1, Bre2,...Bre[N-1]
VecBImag = Bim0, Bim1, Bim2,...Bim[N-1]
Run Code Online (Sandbox Code Playgroud)
我必须运行标量乘法:
VecCReal = Cre0, Cre1, Cre2,...Cre[N-1]
VecCImag = Cim0, Cim1, Cim2,...Cim[N-1]
Cre[i] = Are[i]*Bre[i] - Aim[i]-Bim[i]
Cim[i] = Are[i]*Bim[i] + Aim[i]+Bre[i]
Run Code Online (Sandbox Code Playgroud)
在每次迭代中,我必须_mm_load_ps在 4 个不同的指针上运行。
在 sum、add 之后,在每次迭代中我必须_mm_store_ps在 2 个不同的指针上运行。
由于大量加载/存储,它看起来效率很低。你能建议一个更好的方法吗?
我是 x86 的新手,没有任何经验,所以这段代码对我来说看起来有点过时了。这样做有什么目的吗?
说明是:
rcx+000003F8 = 32 位浮点数
xmm0 = 0(全部 128 位)
movss xmm4,[rcx+000003F8]
unpcklps xmm4,xmm0
Run Code Online (Sandbox Code Playgroud)
“unpcklps xmm4,xmm0”会不会过时,因为它不会改变 xmm4 中的任何内容?
你好论坛 - 我有一些关于SIMD内在的类似/相关问题我在网上搜索了包括stackoverflow但没有找到好的答案所以请求你的帮助.
基本上我试图理解64位CPU如何在一次读取中获取所有128位,以及这种操作的要求是什么.
我发现在为这个看似简单的问题创建代码时遇到了困难.
给定一个打包的8位整数,如果存在则用另一个字节替换另一个字节
举例来说,我想替换0x06用0x01,所以我可以做以下res的输入找到0x06:
// Bytes to be manipulated
res = _mm_set_epi8(0x00, 0x03, 0x02, 0x06, 0x0F, 0x02, 0x02, 0x06, 0x0A, 0x03, 0x02, 0x06, 0x00, 0x00, 0x02, 0x06);
// Target value and substitution
val = _mm_set1_epi8(0x06);
sub = _mm_set1_epi8(0x01);
// Find the target
sse = _mm_cmpeq_epi8(res, val);
// Isolate target
sse = _mm_and_si128(res, sse);
// Isolate remaining bytes
adj = _mm_andnot_si128(sse, res);
Run Code Online (Sandbox Code Playgroud)
现在我不知道如何继续or这两个部分,我需要删除目标并用替换的字节替换它.
我在这里缺少什么SIMD指令?
和其他问题一样,我只限于AVX,我没有更好的处理器.