为什么我在使用MKL时,Tensorflow会对AVX2发出警告?
我正在使用Tensorflow的Anaconda分布和MKL支持. from tensorflow.python.framework import test_util test_util.IsMklEnabled() 此代码打印True.但是,当我编译我的Keras模型时,我仍然会得到 您的CPU支持说明此张力二进制的指示 编译以使用:AVX AVX2 这不是我期望的行为. 解决方案 tensorflow执行的MKL-DNN部分(这是MKL工程师提供的主要加速度)在运行时被jit'Ded.因此,针对二进制创建的指令集与MKL-​​DNN代码无关.它只会影响其他数学,主要是特征库,并且任何函数都没有被MKL-DNN函数替换. 其他解决方案 可以忽略此警告.之所以出现的原因是因为在构建TF时设置了指令集标志.但是,在运行时间内,MKL-DNN(负责在TensorFlow MKL中执行核心计算的数学LIB)将使用机器支持的最新矢量指令集.如果您查看Inte
2 2024-01-26
编程技术问答社区
在AVX2指令中,如果没有快速聚集和散射,你该怎么办?
我正在编写一个程序来检测素数.一部分是筛选可能的候选人.我写了一个相当快的程序,但我想我会看看是否有人有更好的想法.我的程序可以使用一些快速的收集和分散说明,但我仅限于X86体系结构的AVX2硬件(我知道AVX-512有这些,尽管我不确定它们的速度). #include #include #define USE_AVX2 // Sieve the bits in array sieveX for later use void sieveFactors(uint64_t *sieveX) { const uint64_t totalX = 5000000; #ifdef USE_AVX2 uint64_t indx[4], bits[4]; const __m256i sieveX2 = _mm256_set1_epi64x((uint64_t)(sieveX)); const __m256i t
6 2024-01-22
编程技术问答社区
在AVX2中高效地实现log2(__m256d)。
svml的__m256d _mm256_log2_pd (__m256d a)在其他编译器上没有其他编译器,他们说其性能在AMD处理器上残障.在 avx中,互联网上提到了一些实现. g ++中缺少的日志内在(_mm256_log_ps) - 4.8?和 simd simd simd simd simd Math SSE和AVX的库,但是它们似乎比AVX2更具SSE.还有 agner Fog的vector库,但是它是一个只有更多只是矢量log2的大型库,所以从其中的实现中,很难仅找出向量log2操作的基本零件. 那么,有人可以说明如何有效地解释如何为4 double数字实现log2()操作吗? IE.就像__m256d _mm256_log2_pd (__m256d a)一样 编辑:在我当前的特定情况下,这些数字是0到1之间的概率,对数用于熵计算:P[i]*log(P[i])的所有i的总和否定. P[i]的浮点指数的范围很大,因此数字可以接近0.我不确定准确性,因此可以考虑以30位
8 2024-01-22
编程技术问答社区
在函数调用前保存XMM寄存器
在汇编功能调用之前,是否需要保存/将任何XMM寄存器保存到堆栈中? 因为在我的代码中观察崩溃问题,并使用释放模式进行64位开发(使用AVX2).在调试模式下,其工作正常.我尝试保存XMM8寄存器的内容并在函数呼叫结束时恢复它,然后恢复其正常工作. 有任何想法或参考? 解决方案 是的,在Microsoft Windows上,您需要保留XMM6-XMM15寄存器.参见 http://msdn.microsoft.com/en-us/en-us/library/library/7kcdt6fy. aspx - 这包括xmm8,因此要么保留它们,要么不在您的功能中使用它们. 但是,在Linux上,这些是临时记录,因此不必保留.参见 http://www.x86-64.org/documentation/abi.pdf第21页.
8 2023-12-16
编程技术问答社区
支持AVX2的所有CPU都支持BMI2或Popcnt吗?
来自在这里暗示BMI1的支持.那么AVX2:所有支持AVX2的CPU都支持BMI2吗?此外,AVX2的支持是否表示Popcnt的支持? 在Google上进行了搜索,无法找到明确的答案.我获得的最接近的是 avx是否支持BMI1支持? P> 解决方案 所有带有AVX2的真实硬件也具有BMI2. AMD ZEN 2和更早的慢速pdep/pext ,因此,如果您对CPU检测进行CPU检测,则需要检查这些CPU模型而不是BMI2设置功能指针,用于使用循环内部任一指令的函数.其他BMI2说明如果得到支持. 几乎所有的AVX2硬件也具有FMA,但不完全. BMI1/2和FMA3是-march=x86-64-v3特征级别的一部分(本质上是Haswell,但没有TSX,AES-NI,rdrand以及其他一些内容. 尽管pdep和pext和pext and pext and pext确实需要大量的执行单元,但至少在商业上与商业相关的主流CPU中,所有未来的CPU都可能具有AV
2 2023-12-16
编程技术问答社区
高效的(在Ryzen上)提取__m256的奇数元素到__m128的方法?
是否有将AVX寄存器的64位组件的高/低32位组件重新包装到SSE寄存器中?使用AVX2的解决方案是可以的. 到目前为止,我正在使用以下代码,但是Profiler表示 ryzen 1800x : // Global constant const __m256i gHigh32Permute = _mm256_set_epi32(0, 0, 0, 0, 7, 5, 3, 1); // ... // function code __m256i x = /* computed here */; const __m128i high32 = _mm256_castsi256_si128(_mm256_permutevar8x32_epi32(x, gHigh32Permute)); // This seems to take 3 cycles 解决方案 用_mm256_permutevar8x32_ps铸造+铸造的_mm256_permutevar8x32_ps对一个矢
16 2023-12-16
编程技术问答社区
AVX2中的条件指令
您可以提供AVX2中可用的条件说明的列表吗? 到目前为止,我找到了以下内容: _mm256_blendv_*用于从a和b基于Mask c 的选择 是否有条件乘和有条件的添加等等? 另外,如果指示imm8 count(例如_mm256_blend_*),您能解释一下如何在矢量比较之后获得imm8吗? 解决方案 AVX512几乎所有指令都引入了可选的零屏蔽和合并掩模. 在此之前,要进行有条件的添加,请在之前掩盖一个操作数(vandps或vandnps) 而不是vblendvps在结果上).这就是为什么包装兼容说明/内在的全零或全部元素的原因. 0.0是加性身份元素,因此添加它是一个no-op. (除了-0.0和+0.0的IEEE语义外,我忘记了它的工作原理). 掩盖常数输入而不是混合结果避免使关键路径更长,因为有条件地添加1.0. 条件倍数更加麻烦,因为0.0不是乘法身份.您需要乘以1.0才能保持值不变,并且与比较结果相比,您无法轻松地通过
22 2023-12-16
编程技术问答社区
将一个int64_t移到AVX2 __m256i向量的高四位数上。
这个问题类似于[1].但是,我不太了解它是如何使用GPR插入YMM的高四倍词的方法.此外,我希望该操作不使用任何中间内存访问. 可以使用AVX2或以下(我没有AVX512)? [1] 如何以%ymm或%zmm上的特定QWORD位置将双重转移到特定的QWOWS位置? (Kaby Lake或以后) 解决方案 我的答案在链接的问题上没有显示出这样做的方法,因为如果没有avx512f,它就无法做到非常有效的效率(vpbroadcastq zmm0{k1}, rax).但实际上,使用刮擦寄存器并不是那么糟糕,大约与vpinsrq +立即混合的成本相同. (在Intel上,3个UOPS总计.2端口5(VMOVQ +广播),以及可以在任何端口上运行的立即混合物. 请参阅我为此更新了ASM的答案.在C ++具有Intel的内在内容中,您会做类似的事情: #include #include // integer versi
126 2023-12-16
编程技术问答社区
将__m256i的前N位或后N位设置为1,其余为0的有效方法
如何使用AVX2 有效地设置为1 第一个N位 最后N位 __m256i的 ,将其余的设置为0? 这些是范围内和结束__m256i值的范围时的两个单独的操作.占用完整__m256i值的范围的一部分是用all-0或all- 1掩码处理的. 解决方案 AVX2 Shift指令vpsllvd和vpsrlvd具有偏移计数的不错的属性 大于或等于32导向YMM寄存器内的零整数. 换句话说:相比之下,转移计数没有被掩盖 x86标量偏移指令的偏移计数. 因此,代码很简单: /* gcc -O3 -m64 -Wall -mavx2 -march=broadwell avx2_bit_mask.c */ #include #include __m256i bit_mask_avx2_msb(unsigned int n) { __m256i ones = _mm25
10 2023-12-16
编程技术问答社区
为什么有些Haswell AVX的延迟被英特尔宣传为比Sandy Bridge慢3倍?
在Intel interinsics webapp ,似乎有几项操作从桑迪桥到Haswell.例如,许多插入操作(例如_mm256_insertf128_si256)显示一个成本表,如下: Performance Architecture Latency Throughput Haswell 3 - Ivy Bridge 1 - Sandy Bridge 1 - 我发现这种差异令人困惑.这种差异是因为有一些新的说明代替这些指令或补偿了这些说明(哪些)?有人知道Skylake是否进一步改变了此模型? 解决方案 tl:dr :所有车道 - 跨散档/插入/提取物/提取物在haswell/skylake上具有3c延迟,但根据这可能是执行单元中的1c +不可避免的旁路延迟,因为. (SKL使一些UOPS UOPS 4C,包括FMA/ADDPS/MULP). (请注意,在使用1
6 2023-12-16
编程技术问答社区
XGETBV和CPUID检查是否足以保证AVX2支持?
在这个问题中,确认__builtin_cpu_supports("avx2")没有检查OS支持. (或者至少在gcc int check_xcr0_ymm() { uint32_t xcr0; #if defined(_MSC_VER) xcr0 = (uint32_t)_xgetbv(0); /* min VS2010 SP1 compiler is required */ #else __asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" ); #endif return ((xcr0 & 6) == 6); /* checking if xmm and ymm state are enabled in XCR0 */ } 问题:此检查加上CPUID检查足以保证AVX2说明不会崩溃我的程序? 奖金问题:这是该检查实际在做什么?为什么存在? (有一些讨论在这里3154996">在这里,但我认为这个话题值得一个专用的答案.
2 2023-12-16
编程技术问答社区
为什么使用AVX2的速度比预期低?
我已经使用avx2的内在指令对矩阵添加的内部循环进行了矢量,我还从这是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
6 2023-12-15
编程技术问答社区
在水平方向上以奇数顺序添加矢量元素的最快方法是什么?
根据这个问题在这段时间实现了水平添加5 x 5和7 x 7,它可以正确完成工作,但不够快. 可以比它快吗?我尝试使用hadd和其他指令,但改进是限制的.对于审查,当我使用_mm256_bsrli_epi128时,它稍好一些,但需要一些额外的排列,以破坏车道的利益.因此,问题是如何实施它以获得更多的绩效.同样的故事是针对9个元素等的 这水平增加了5个元素,并将结果放在0、5和10的位置: //it put the results in places 0, 5, and 10 inline __m256i _mm256_hadd5x5_epi16(__m256i a ) { __m256i a1, a2, a3, a4; a1 = _mm256_alignr_epi8(_mm256_permute2x128_si256(a, _mm256_setzero_si256(), 0x31), a, 1 * 2); a2 = _mm256_alignr_ep
4 2023-12-15
编程技术问答社区
循环AVX的最佳方法是什么?
如果数组不能除以8(对于整数),那么为其编写周期的最佳方法是什么?到目前为止,我可能想出的可能的方法是将其分为两个单独的周期:几乎所有元素的1个主周期;和1个带有遮罩/蒙版的尾循环,用于剩余的1-7个元素.但这看起来不是最好的方法. for (auto i = 0; i
8 2023-12-15
编程技术问答社区
2个32位数相乘,用AVX2取前32位
我正在使用乘法(加上其他操作)作为整数划分的替代.我的解决方案最终要求我将2个32位数字乘在一起,并取得前32位(就像Mulhi功能一样),但是AVX2不提供_mm256_mulhi_epu16的32位变体(例如:没有'_mmm256_mulhi_epu32'函数). 我尝试了各种方法,例如检查AVX512的功能,甚至操纵32位整数为2个HI/LO 16位整数.我对使用低级编程的新手很新,所以我不知道什么是最佳的,甚至可能是可能的. 解决方案 这可以通过以下操作来完成: __m256i t1 = _mm256_mul_epu32(m, n); t1 = _mm256_srli_epi64(t1, 32);
6 2023-12-15
编程技术问答社区
用矢量指令进行复杂的数据重组
我需要将12个字节加载到16(或24分为32)之后,遵循以下模式: ABC DEF GHI JKL 变成 ABBC DEEF GHHI JKKL 您能否提出有效的方法来使用SSE(2)和/或AVX(2)说明? 需要重复执行此操作,因此可以预先存储的掩码或常数. 解决方案 到目前为止,您最好的选择是使用字节冲洗(pshufb).在元素中移动本身还不够,因为JKL必须向右移动比DEF等.等等.因此,您需要多个指令来进行不同的偏移并融合结果. pshufb(_mm_shuffle_epi8)需要SSSE3,但可以在单个快速指令中完成12B-> 16B的作业.它使用矢量作为洗牌控制面具.这是第一个可变控制的混乱,也是第一个柔性字节散装. (SSE2散装所有使用IMM8控制操作数,或具有固定的数据移动(例如punpcklbw). 编写一个加载16B,将第一个12B的循环编写成16B,然后存储.使用未对准的负载,并在必要时使用未对准的商店.代替标量清理循
6 2023-12-15
编程技术问答社区
由8x __m256i寄存器代表的矩阵的AVX2转座
我试图弄清楚如何转置(在avx2 intinsics中)一个由__m256i寄存器的8行组成的矩形矩阵,每个矩阵都包含32x 8位(char). __m256i matrix[8]; //32x8bit integers 转置矩阵就像32行8 x 8位整数,但我也可以以相同的方式表示它:8行__m256i,每个行包含4行64位. > . 我知道_mm256_shuffle_epi8适合这种问题,但我不知道如何使用矩形矩阵的特定情况. 解决方案 这个想法是从将32个字符的__m256i行视为8 32位整数. 然后矩阵__m256i matrix[8]可以看作是8x8整数矩阵. 现在,通过转换此8x8整数矩阵来获得该解决方案,其次是 __m256i寄存器中的一些字节置换. 对于8x8整数转置我们 使用 Z Boson的答案的"标准" 8x8浮动转座. 有些从si256到ps,反之亦然,我们可以将其用于8x8 Integer Case. 函数transpos
0 2023-12-15
编程技术问答社区
AVX或SSE上的水平尾部最大值
i有一个由16位值组成的__m256i寄存器,我想在每个尾声元素上获取最大值. 举一个例子: input: 1 0 0 3 0 0 4 5 0 0 0 0 4 3 0 2 output: 1 1 1 3 3 3 4 5 5 5 5 5 4 3 3 2 在AVX或AVX架构上是否有任何有效的方法?也许使用log(16)= 4迭代? 加法: 也对128位数字进行8个UINT_16的任何解决方案也要赞赏. 解决方案 您确实可以在log_2(SIMD_width)步骤中执行此操作.这个想法是移动输入向量x_vec两个字节.然后我们融合 x_vec使用移位向量,因此x_vec被移位的向量替换,但仅在x_vec的零位置. 该过程以4、8和16字节的偏移重复.您可以在代码中删除printf -s,以查看x_vec和x_trail之间会发生什么. #include #include /* gcc -O3 -Wall
10 2023-12-15
编程技术问答社区
如何在水平方向上将AVX2矢量添加为3乘3?
i具有包含16x16位元素的__m256i向量.我想在其上应用三个相邻的水平添加.在标量模式下,我使用以下代码: unsigned short int temp[16]; __m256i sum_v;//has some values. 16 elements of 16-bit vector. | 0 | x15 | x14 | x13 | ... | x3 | x2 | x1 | _mm256_store_si256((__m256i *)&temp[0], sum_v); output1 = (temp[0] + temp[1] + temp[2]); output2 = (temp[3] + temp[4] + temp[5]); output3 = (temp[6] + temp[7] + temp[8]); output4 = (temp[9] + temp[10] + temp[11]); output5 = (temp[12] + temp[13] + temp
0 2023-12-15
编程技术问答社区