Tag: sse

如何初始化范围从0到N的SIMD向量?

我有以下函数我正在尝试编写一个AXV版本: void hashids_shuffle(char *str, size_t str_length, char *salt, size_t salt_length) { size_t i, j, v, p; char temp; if (!salt_length) { return; } for (i = str_length – 1, v = 0, p = 0; i > 0; –i, ++v) { v %= salt_length; p += salt[v]; j = (salt[v] + v + p) % […]

使用SIMD优化1D热方程

我正在使用CFD代码(用于计算流体动态)。 我最近有机会在我的一个循环中看到英特尔编译器使用SSE,在这个循环中为计算性能增加了近2倍的因子。 但是,使用SSE和SIMD指令似乎更像是运气。 大多数情况下,编译器什么都不做。 我正在尝试强制使用SSE,考虑到AVX指令将在不久的将来强化这一方面。 我做了一个简单的1D热转印代码。 它由两个阶段组成,使用另一个阶段的结果(U0 – > U1,然后是U1 – > U0,然后是U0 – > U1等)。 当它迭代时,它会收敛到稳定的解决方案。 主代码中的大部分循环都使用相同的计算方式。 (有限差分)。 但是,我的代码比普通循环慢两倍。 结果是相同的,因此计算是一致的。 我弄错了吗? 在使用Westmer进行测试之前,我正在使用Core 2来测试循环。 这是代码,带有SSE循环,然后是引用循环: #include #include #include //#include #define n1 1004 #define niter 200000 int i,j,t; double U0[n1] __attribute__ ((aligned(16))); double U1[n1] __attribute__ ((aligned(16))); double Dx,Dy,Lx,Ly,InvDxDx,Dt,alpha,totaltime,Stab,DtAlpha,DxDx; __m128d vmmx00; __m128d vmmx01; __m128d vmmx02; __m128d vmmx10; […]

用于GCC划分的SIMD(SSE)指令

如果可能,我想使用SSE指令优化以下代码段: /* * the data structure */ typedef struct v3d v3d; struct v3d { double x; double y; double z; } tmp = { 1.0, 2.0, 3.0 }; /* * the part that should be “optimized” */ tmp.x /= 4.0; tmp.y /= 4.0; tmp.z /= 4.0; 这有可能吗?

移位n位的__m128i

我有一个__m128i变量,我需要将其n位的128位值移位,即_mm_srli_si128和_mm_slli_si128工作,但是在位而不是字节上。 这样做最有效的方法是什么?

最佳SSE无符号8位比较

我试图找到使用SSE执行8位无符号比较的最多方法(直到SSE 4.2)。 我正在研究的最常见的情况是比较> 0U,例如 _mm_cmpgt_epu8(v, _mm_setzero_si128()) // #1 (这当然也可以被认为是非零的简单测试。) 但我对更一般的情况也有点兴趣,例如 _mm_cmpgt_epu8(v1, v2) // #2 第一种情况可以使用各种不同的方法用2条指令实现,例如与0比较然后反转结果。 第二种情况通常需要3条指令,例如从两个操作数中减去128并执行带符号的比较。 (有关各种3种指令解决方案,请参阅此问题 。) 理想情况下,我正在寻找#1的单指令解决方案,以及#2的双指令解决方案。 如果这些都不可能,那么我也对在现代英特尔CPU(Sandy Bridge,Ivy Bridge,Haswell)上哪种各样的可能的2或3指令实现最有效的想法感兴趣。 到目前为止,案例#2的最佳实现: 比较等于无符号最大值和反转结果: #define _mm_cmpgt_epu8(v0, v1) \ _mm_andnot_si128(_mm_cmpeq_epi8(_mm_max_epu8(v0, v1), v1), \ _mm_set1_epi8(-1)) 两个算术指令+一个按位= 1.33吞吐量。 反转两个参数的符号位(==减去128)并使用带符号的比较: #define _mm_cmpgt_epu8(v0, v1) \ _mm_cmpgt_epi8(_mm_xor_si128(v0, _mm_set1_epi8(-128)), \ _mm_xor_si128(v1, _mm_set1_epi8(-128))) 一个算术指令+两个按位= 1.16吞吐量。 案例#1的最佳实现,源自上面的案例#2实现: 1。 #define _mm_cmpgtz_epu8(v0) \ _mm_andnot_si128(_mm_cmpeq_epi8(v0, _mm_set1_epi8(0)), \ […]

快速逐字节替换if

我有一个函数可以将二进制数据从一个区域复制到另一个区域,但前提是这些字节与特定值不同。 这是一个代码示例: void copy_if(char* src, char* dest, size_t size, char ignore) { for (size_t i = 0; i < size; ++i) { if (src[i] != ignore) dest[i] = src[i]; } } 问题是这对我目前的需求来说太慢了。 有没有办法以更快的方式获得相同的结果? 更新:基于答案,我尝试了两个新的实现: void copy_if_vectorized(const uint8_t* src, uint8_t* dest, size_t size, char ignore) { for (size_t i = 0; i < size; ++i) { […]

SSE:如果不是零,则为倒数

如何使用SSE指令获取浮点数的倒数(反向),但仅适用于非零值? 背景情况: 我想规范化一组向量,以便每个维度具有相同的平均值。 在C中,这可以编码为: float vectors[num * dim]; // input data // step 1. compute the sum on each dimension float norm[dim]; memset(norm, 0, dim * sizeof(float)); for(int i = 0; i < num; i++) for(int j = 0; j < dims; j++) norm[j] += vectors[i * dims + j]; // step 2. convert sums […]

SIMD以下代码

如何在C中简化以下代码(当然使用SIMD内在函数)? 我无法理解SIMD内在函数,这会有很大帮助: int sum_naive( int n, int *a ) { int sum = 0; for( int i = 0; i < n; i++ ) sum += a[i]; return sum; }

当程序将受益于预取和非临时加载/存储?

我做了一个测试 for (i32 i = 0; i < 0x800000; ++i) { // Hopefully this can disable hardware prefetch i32 k = (i * 997 & 0x7FFFFF) * 0x40; _mm_prefetch(data + ((i + 1) * 997 & 0x7FFFFF) * 0x40, _MM_HINT_NTA); for (i32 j = 0; j < 0x40; j += 0x10) { //__m128 v = […]

使用较新版本的SIMD版本是否可用?

当我可以使用SSE3或AVX时,可以使用SSE2或MMX等较旧的SSE版本 – 或者我还需要单独检查它们吗?