我在一些C代码中使用AVX2指令。 VPERMD指令采用两个8整数向量a和idx并通过基于idx置换a来生成第三个向量dst 。 这似乎相当于dst[i] = a[idx[i]] for i in 0..7 。 我正在调用此源代码,因为该移动是基于源索引的。 但是,我有基于目的地forms的计算索引。 这对于设置数组是很自然的,相当于dst[idx[i]] = a[i] for i in 0..7 。 如何从基于源的表单转换为基于目标的表单? 一个示例测试用例是: {2 1 0 5 3 4 6 7} source-based form. {2 1 0 4 5 3 6 7} destination-based equivalent 对于这种转换,我留在ymm寄存器中,这意味着基于目标的解决方案不起作用。 即使我要单独插入每个,因为它只在常量索引上运行,你不能只设置它们。
我使用AVX2,C中的FMA制作了矩阵向量乘法程序。我使用GCC ver7编译了-mfma,-mavx。 但是,我收到错误“释放对象的校验和不正确 – 对象可能在被释放后被修改。” 我认为如果矩阵维度不是4的倍数,则会产生错误。 我知道AVX2使用ymm寄存器,可以使用4个双精度浮点数。 因此,如果矩阵是4的倍数,我可以毫无错误地使用AVX2。 但是,这是我的问题。 如果矩阵不是4的倍数,我怎样才能有效地使用AVX2 ??? 这是我的代码。 #include “stdio.h” #include “math.h” #include “stdlib.h” #include “time.h” #include “x86intrin.h” void mv(double *a,double *b,double *c, int m, int n, int l) { __m256d va,vb,vc; int k; int i; for (k = 0; k < l; k++) { vb = _mm256_broadcast_sd(&b[k]); for (i = […]
我试图熟悉一些较新的英特尔处理器上提供的256位AVX指令。 我已经validation我的i7-4720HQ支持256位AVX指令。 我遇到的问题是VMOVAPS指令,它应该复制8个单精度浮点值,只复制4。 dot PROC VMOVAPS YMM1, ymmword ptr [RCX] VDPPS YMM2, YMM1, ymmword ptr [RDX], 255 VMOVAPS ymmword ptr [RCX], YMM2 MOVSS XMM0, DWORD PTR [RCX] RET dot ENDP 如果您不熟悉调用约定,Visual C ++ 2015期望在返回时返回此函数(因为它是一个浮点数)在XMM0中。 除此之外,标准是第一个参数在RCX中传递,第二个参数在RDX中传递。 这是调用此函数的C代码。 _declspec(align(32)) float d1[] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; _declspec(align(32)) float d2[] = { […]
我正在使用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?
在优化arrays压缩的问题中,最佳答案指出: 具有最新指令集的SSE / AVX寄存器允许更好的方法。 我们可以直接使用PMOVMSKB的结果,将其转换为PSHUFB之类的控制寄存器。 Haswell(AVX2)可以实现吗? 或者它需要AVX512的一种口味? 我有一个包含int32s的AVX2向量,以及一个比较结果的相应向量。 我想以某种方式将其改组,以便在掩码中设置相应msb的元素(比较true)在向量的低端是连续的。 我能看到的最好的是使用_mm256_movemask_ps / vmovmskps(没有* d变体?)得到一个掩码,然后在256 AVX2向量查找表中使用它来获得跨通道_m256_permutevar8x32_epi32 / vpermd的随机掩码
我已经使用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 , […]
基本上我怎么能用AVX2内在函数写出相当于这个? 我们假设result_in_float的类型为__m256 ,而result的类型为short int*或short int[8] 。 for(i = 0; i < 8; i++) result[i] = (short int)result_in_float[i]; 我知道使用__m256i _mm256_cvtps_epi32(__m256 m1)内在函数可以将浮点数转换为32位整数,但不知道如何将这些32位整数进一步转换为16位整数。 我不仅仅想要这样,而且还要将这些值(以16位整数的forms)存储到存储器中,我想使用向量指令来完成所有这些操作。 在互联网上搜索,我找到了一个名为_mm256_mask_storeu_epi16的内在函数,但是我不确定是否会这样做,因为我找不到它的用法示例。
我知道通常应避免跨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; } } 没有去往/从记忆中这样做的好方法是什么?
如何清除m2的高128位: __m256i m2 = _mm256_set1_epi32(2); __m128i m1 = _mm_set1_epi32(1); m2 = _mm256_castsi128_si256(_mm256_castsi256_si128(m2)); m2 = _mm256_castsi128_si256(m1); 不起作用 – 英特尔的_mm256_castsi128_si256内在文档说“结果向量的高位未定义”。 同时我可以在assembly中轻松完成: VMOVDQA xmm2, xmm2 //zeros upper ymm2 VMOVDQA xmm2, xmm1 当然我不想使用“和”或_mm256_insertf128_si256()等。
当使用C的GCC向量扩展时,如何检查向量上的所有值是否为零? 例如: #include typedef uint32_t v8ui __attribute__ ((vector_size (32))); v8ui* foo(v8ui *mem) { v8ui v; for ( v = (v8ui){ 1, 1, 1, 1, 1, 1, 1, 1 }; v[0] || v[1] || v[2] || v[3] || v[4] || v[5] || v[6] || v[7]; mem++) v &= *(mem); return mem; } SSE4.2具有PTEST指令,允许运行类似于for条件的测试for但GCC生成的代码只是解包向量并逐个检查单个元素: .L2: vandps (%rax), […]