SSE2具有在单精度浮点数和32位整数之间转换向量的指令.
_mm_cvtps_epi32()_mm_cvtepi32_ps()但是没有双精度和64位整数的等价物.换句话说,他们失踪了:
_mm_cvtpd_epi64()_mm_cvtepi64_pd()似乎AVX也没有它们.
模拟这些内在函数的最有效方法是什么?
我改编了我在 SO 上找到的 SSE2 函数,并将其包含在我的程序中。该函数使用 SSE2 内在函数来计算向量中每个 8 x 16 位整数的前导零计数。当我编译这个程序时,它没有产生任何警告,并在我经常用于开发的旧笔记本电脑上运行它,它崩溃并显示消息“非法指令(核心转储)”。在检查程序集时,我注意到我的函数似乎具有 AVX1“VEX”编码的 SSE2 指令,如下所示。
.globl _mm_lzcnt_epi32
.type _mm_lzcnt_epi32, @function
_mm_lzcnt_epi32:
.LFB5318:
.cfi_startproc
endbr64
vmovdqa64 %xmm0, %xmm1
vpsrld $8, %xmm0, %xmm0
vpandn %xmm1, %xmm0, %xmm0
vmovdqa64 .LC0(%rip), %xmm1
vcvtdq2ps %xmm0, %xmm0
vpsrld $23, %xmm0, %xmm0
vpsubusw %xmm0, %xmm1, %xmm0
vpminsw .LC1(%rip), %xmm0, %xmm0
ret
.cfi_endproc
Run Code Online (Sandbox Code Playgroud)
如果我将头文件 immintrin.h 更改为 emmintrin.h,它会将我的代码正确编译为 SSE2 指令
.globl _mm_lzcnt_epi32
.type _mm_lzcnt_epi32, @function
_mm_lzcnt_epi32:
.LFB567:
.cfi_startproc
endbr64
movdqa %xmm0, %xmm1
psrld $8, %xmm0
pandn %xmm1, %xmm0
cvtdq2ps %xmm0, …Run Code Online (Sandbox Code Playgroud) 我正在修改AVX-2指令,我正在寻找一种快速计算__m256i单词中前导零数(具有256位)的方法.
到目前为止,我已经找到了以下方法:
// Computes the number of leading zero bits.
// Here, avx_word is of type _m256i.
if (!_mm256_testz_si256(avx_word, avx_word)) {
uint64_t word = _mm256_extract_epi64(avx_word, 0);
if (word > 0)
return (__builtin_clzll(word));
word = _mm256_extract_epi64(avx_word, 1);
if (word > 0)
return (__builtin_clzll(word) + 64);
word = _mm256_extract_epi64(avx_word, 2);
if (word > 0)
return (__builtin_clzll(word) + 128);
word = _mm256_extract_epi64(avx_word, 3);
return (__builtin_clzll(word) + 192);
} else
return 256; // word is entirely zero
Run Code Online (Sandbox Code Playgroud)
但是,我发现在256位寄存器中找出确切的非零字是相当笨拙的.
有人知道是否有更优雅(或更快)的方法吗?
正如附加信息:我实际上想要计算由逻辑AND创建的任意长向量的第一个设置位的索引,并且我将标准64位操作的性能与SSE和AVX-2代码进行比较.这是我的整个测试代码:
#include <stdio.h> …Run Code Online (Sandbox Code Playgroud) 我正在处理一个处理秘密数据的 SGX 项目,在某些时候,我需要评估浮点数的自然对数。评估过程应该是抗边信道的,这意味着它的运行时间和内存访问模式将独立于它的输入和输出。
在野外有这样的实现吗?这个问题在文献中解决了吗?