Tag: intrinsics

SSE字节和半字交换

我想使用SSE内在函数翻译此代码。 for (uint32_t i = 0; i > 16) & 0xFFFF) | (value << 16); } 是否有人知道执行16位字交换的内在函数?

128乘法和除法的内在函数

在x86_64中,我知道mul和div的代码通过将低64位放在rax中而高位放在rdx寄存器中来支持128个整数。 我在intel intrinsics指南中寻找某种内在的function,我找不到一个。 我正在写一个大字库,字大小为64位。 现在我正在用这样一个单词进行划分。 int ubi_div_i64(ubigint_t* a, ubi_i64_t b, ubi_i64_t* rem) { if(b == 0) return UBI_MATH_ERR; ubi_i64_t r = 0; for(size_t i = a->used; i– > 0;) { ubi_i64_t out; __asm__(“\t” “div %[d] \n\t” : “=a”(out), “=d”(r) : “a”(a->data[i]), “d”(r), [d]”r”(b) : “cc”); a->data[i] = out; //ubi_i128_t top = (r <data[i]; //r = […]

Howto vblend 32位整数? 或者:为什么没有_mm256_blendv_epi32?

我正在使用AVX2 x86 256位SIMD扩展。 我想做一个32位整数组件if-then-else指令。 在英特尔文档中,这样的指令称为vblend。 Intel内部指南包含函数_mm256_blendv_epi8。 这个function几乎可以满足我的需求。 唯一的问题是它适用于8位整数。 遗憾的是,文档中没有_mm256_blendv_epi32。 我的第一个问题是:为什么这个function不存在? 我的第二个问题是:如何模仿它? 经过一番搜索后,我找到了_mm256_blendv_ps,这就是我想要的32位浮点数。 此外,我发现了转换函数_mm256_castsi256_ps和_mm256_castps_si256,它们从整数转换为32位浮点数并返回。 把这些放在一起给出: inline __m256i _mm256_blendv_epi32 (__m256i a, __m256i b, __m256i mask){ return _mm256_castps_si256( _mm256_blendv_ps( _mm256_castsi256_ps(a), _mm256_castsi256_ps(b), _mm256_castsi256_ps(mask) ) ); } 虽然这看起来像5个函数,但其​​中4个只是美化的强制转换,而另一个直接映射到处理器指令。 因此,整个function归结为一个处理器指令。 因此,真正令人尴尬的部分是似乎有一个32位的blendv,除了缺少相应的内在函数。 是否有一些边境案例,这将失败? 例如,当整数位模式恰好代表浮点NAN时会发生什么? blendv会忽略这个还是会引发一些信号? 万一这是有效的:我是否正确,有一个8位,一个32位和一个64位的blendv但是缺少一个16位的blendv?

gcc(6.1.0)在SSE内在函数中使用’错误’指令

背景 :我开发了一个用C / C ++编写的计算密集型工具,它必须能够在各种不同的x86_64处理器上运行。 为了加速浮点数和整数计算,代码包含了很多SSE *内在函数,它们具有针对不同CPU SSEfunction定制的不同路径。 (由于在程序开始时检测到CPU标志并用于设置布尔值,我假设对定制的代码块的分支预测将非常有效地工作)。 为简单起见,我假设只需要考虑SSE2到SSE4.2。 为了访问4.2路径的SSE4.2内在函数fpr,我需要使用gcc的-msse4.2选项。 问题我遇到的问题是,至少使用6.1.0,gcc使用sse4.2指令pinrd来实现sse2内部函数mm_cvtsi32_si128。 如果我使用-msse2限制编译,它将使用sse2指令,movd,即。 英特尔“内在指南”说它应该使用的那个。 这有点令人讨厌。 1)关键问题是,当程序在pre4.2 CPU上运行时,程序现在会因非法指令而崩溃。 我无法控制使用何种硬件,因此可执行文件需要与旧机器兼容,但需要利用新硬件上的function。 2)根据英特尔内在指南,pinrd指令比它取代的mov慢得多。 (pinsrd更通用但不需要这样)。 有谁知道如何使gcc 只使用内在指南所说的应该使用的指令,但仍然允许在同一个编译单元中通过SSE4 *访问所有SSE2? 更新:我还应该注意,在Linux,Windows和OSX下使用各种不同的编译器编译相同的代码,因此如果可能的话,更愿意避免或至少拥有最少的编译器特定扩展。 Update2 :(感谢@PeterCordes)似乎如果启用了优化,gcc将在适当的时候恢复使用来自pinsrd的movd。

是否可以在Altivec中旋转128位值?

我正在尝试将一些ARM NEON代码移植到AltiVec。 我们的NEON代码有两个LOAD,一个ROT,一个XOR和一个STORE,所以它看起来像一个简单的测试用例。 根据IBM的vec_rl文档: 结果的每个元素是通过将左边的相应元素旋转由b的相应元素指定的位数来获得的。 除了-qarch=power8 ,doc继续说vector unsigned int是最大的数据类型,在这种情况下, vector unsigned long long适用。 我想执行128位旋转,而不是单个元素的32位或64位旋转。 位位置为19,31,67,97和109.它们不是字节对齐的。 (常量来自ARIA分组密码 )。 4×32和2×64是最大的AltiVec数据安排吗? 是否可以在Altivec中旋转128位值? 如果打包旋转是唯一可用的操作,那么最好在C或AltiVec中进行操作吗?

SSE加载和添加

假设我有两个向量由两个double类型的数组表示,每个数组大小为2.我想添加相应的位置。 因此假设向量i0和i1 ,我想将i0[0] + i1[0]和i0[1] + i1[1]在一起。 由于类型是double ,我需要两个寄存器。 诀窍是将i0[0]和i1[0] ,以及i0[1]和i1[1]放在另一个中,只需添加寄存器即可。 我的问题是,如果我调用_mm_load_ps(i0[0])然后_mm_load_ps(i1[0]) ,它会将它们分别置于低位和高位64位,还是会用第二次load替换寄存器? 如何将两个双打放在同一个寄存器中,以便我可以在之后调用add_ps ? 谢谢,

gcc的__builtin_cpu_supports检查OS支持吗?

GCC编译器提供了一组内置函数来测试某些处理器function,例如某些指令集的可用性。 但是,根据这个线程,我们也可能知道操作系统可能无法启用某些cpufunction。 所以问题是: __builtin_cpu_supports intrinsics还检查操作系统是否启用了某些处理器function?

使用AVX2为什么加速比低于预期?

我已经使用AVX2的内在指令向量化了矩阵加法的内部循环,我也有这里的延迟表。 我预计加速应该是5的因子,因为在128次迭代中,在6次延迟的1024次迭代中发生了近4次延迟,但是加速是3的因数。所以问题是这里还有什么我看不到的。 我正在使用gcc,在c中编码,内在函数,CPU是skylake 6700hq 这是内循环的c和汇编输出。 全球数据: int __attribute__(( aligned(32))) a[MAX1][MAX2] ; int __attribute__(( aligned(32))) b[MAX2][MAX3] ; int __attribute__(( aligned(32))) c_result[MAX1][MAX3] ; 顺序: for( i = 0 ; i < MAX1 ; i++) for(j = 0 ; j < MAX2 ; j++) c_result[i][j] = a[i][j] + b[i][j]; .L16: movl (%r9,%rax), %edx // latency : 2 , […]

确定__m256值的SIMD通道的最小值

我知道通常应避免跨SIMD通道的操作。 但是,有时必须这样做。 我正在使用AVX2内在函数,并在__m256中有8个浮点值。 我想知道这个向量中的最低值,并使问题复杂化:也就是在哪个插槽中。 我目前的解决方案是内存往返,我不喜欢: float closestvals[8]; _mm256_store_ps( closestvals, closest8 ); float closest = closestvals[0]; int closestidx = 0; for ( int k=1; k<8; ++k ) { if ( closestvals[k] < closest ) { closest = closestvals[ k ]; closestidx = k; } } 没有去往/从记忆中这样做的好方法是什么?

如何访问SHA内在函数?

Gprof告诉我,我计算量很大的程序花费大部分时间(36%)使用AP-Hash进行散列。 我无法减少通话次数,但我仍然想让它更快,我可以从ac程序中调用内部SHA吗? 我需要intel编译器还是可以坚持使用gcc?