Tag: sse

从基于来源的指数转换为基于目的地的指数

我在一些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寄存器中,这意味着基于目标的解决方案不起作用。 即使我要单独插入每个,因为它只在常量索引上运行,你不能只设置它们。

FLT_EPSILON用于具有SSE / AVX的第n个根查找器

我正在尝试转换一个函数,在C中找到第n个根,从以下链接http://rosettacode.org/wiki/Nth_root#C获取一个double值,使用AVX一次找到8个浮点数的第n个根。 部分代码使用DBL_EPSILON * 10.但是,当我将其转换为使用浮点数和AVX时,我必须使用FLT_EPSILON * 1000或代码挂起并且不会收敛。 当我打印出FLT_EPSILON时,我看到它是订单1E-7。 但是这个链接http://www.cplusplus.com/reference/cfloat/表示它应该是1E-5。 当我打印出DBL_EPSILON时它是1E-16但链接说它应该只是1E-9。 这是怎么回事? 这是迄今为止的代码(未完全优化)。 #include #include #include // AVX inline double abs_(double x) { return x >= 0 ? x : -x; } double pow_(double x, int e) { double ret = 1; for (ret = 1; e; x *= x, e >>= 1) { if ((e & […]

SSE字节和半字交换

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

使用SSE内在函数的大小为100 * 100的矩阵乘法

int MAX_DIM = 100; float a[MAX_DIM][MAX_DIM]__attribute__ ((aligned(16))); float b[MAX_DIM][MAX_DIM]__attribute__ ((aligned(16))); float d[MAX_DIM][MAX_DIM]__attribute__ ((aligned(16))); /* * I fill these arrays with some values */ for(int i=0;i<MAX_DIM;i+=1){ for(int j=0;j<MAX_DIM;j+=4){ for(int k=0;k<MAX_DIM;k+=4){ __m128 result = _mm_load_ps(&d[i][j]); __m128 a_line = _mm_load_ps(&a[i][k]); __m128 b_line0 = _mm_load_ps(&b[k][j+0]); __m128 b_line1 = _mm_loadu_ps(&b[k][j+1]); __m128 b_line2 = _mm_loadu_ps(&b[k][j+2]); __m128 b_line3 = _mm_loadu_ps(&b[k][j+3]); result = […]

使用SSE(x * x * x)+(y * y * y)进行乘法

我正在尝试使用SIMD优化此function,但我不知道从哪里开始。 long sum(int x,int y) { return x*x*x+y*y*y; } 反汇编函数如下所示: 4007a0: 48 89 f2 mov %rsi,%rdx 4007a3: 48 89 f8 mov %rdi,%rax 4007a6: 48 0f af d6 imul %rsi,%rdx 4007aa: 48 0f af c7 imul %rdi,%rax 4007ae: 48 0f af d6 imul %rsi,%rdx 4007b2: 48 0f af c7 imul %rdi,%rax 4007b6: 48 8d 04 02 […]

矢量*矩阵产品效率问题

正如Z boson 推荐的那样 ,我使用的是列主矩阵格式,以避免使用点积。 但是,在将矢量与矩阵相乘时,我没有看到避免它的可行方法。 矩阵乘法技巧需要有效提取行(或列,如果我们转置产品)。 为了将矢量乘以矩阵,我们因此转置: (b * A)^T = A^T * b^T A是矩阵, b是行向量,在被转置之后变为列向量。 它的行只是单个标量,矢量*矩阵乘积实现成为(非转置)矩阵A和b的列点积的低效实现。 有没有办法避免执行这些点产品? 我认为可以做到的唯一方法是涉及行提取,这对于列主矩阵格式来说是低效的。

计算大型CRC32的正确方法是什么?

这篇文章描述了如何使用现代x86-64处理器中的内置CRC32指令计算最大1024字节的CRC32。 但是,我需要计算超过1024字节的CRC32。 计算1024字节的每个块的CRC32并最终求和它们是否是正确的方法,还是不正确? 如果是这样,那么正确的方法是什么?

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。

SSE FPU并行

我想知道是否可以将SSE与x87并行使用。 所以考虑以下伪代码, 1:sse_insn 2:x87_insn 管道是否会并行执行1和2,假设它们可以并行执行?