Tag: simd

一个更好的8×8字节矩阵转置与SSE?

我发现这篇文章解释了如何通过24次操作转置8×8字节矩阵,稍后会有几个滚动条实现转置。 但是,这种方法没有利用我们可以阻止 8×8转置为4个4×4转置的事实,并且每个转换只能在一个shuffle指令中完成( 这篇文章是参考文献)。 所以我推出了这个解决方案: __m128i transpose4x4mask = _mm_set_epi8(15, 11, 7, 3, 14, 10, 6, 2, 13, 9, 5, 1, 12, 8, 4, 0); __m128i shuffle8x8Mask = _mm_setr_epi8(0, 1, 2, 3, 8, 9, 10, 11, 4, 5, 6, 7, 12, 13, 14, 15); void TransposeBlock8x8(uint8_t *src, uint8_t *dst, int srcStride, int dstStride) { __m128i load0 […]

执行__builtin_clz

GCC(4.6+)__builtin_clz的实施是什么? 它是否与Intel x86_64 (AVX)上的某些CPU指令相对应?

快速计算两个数组之间的相等字节数

我写了函数int compare_16bytes(__m128i lhs, __m128i rhs) ,以便使用SSE指令比较两个16字节数:此函数返回执行比较后相等的字节数。 现在我想使用上面的函数来比较任意长度的两个字节数组:长度可能不是16字节的倍数,所以我需要处理这个问题。 我怎样才能完成下面这个function的实现? 我怎样才能改进下面的function? int fast_compare(const char* s, const char* t, int length) { int result = 0; const char* sPtr = s; const char* tPtr = t; while(…) { const __m128i* lhs = (const __m128i*)sPtr; const __m128i* rhs = (const __m128i*)tPtr; // compare the next 16 bytes of s […]

快速24位arrays – > 32位arrays转换?

快速摘要: 我有一个24位值的数组。 关于如何快速将各个24位数组元素扩展为32位元素的任何建议? 细节: 我正在使用DirectX 10中的Pixel Shaders实时处理传入的video帧。一个绊脚石是我的帧从捕获硬件进入24位像素(作为YUV或RGB图像),但DX10需要32位像素纹理。 因此,在将其加载到GPU之前,我必须将24位值扩展为32位。 我真的不在乎我将剩余的8位设置为什么,或者输入的24位是否在32位值中 – 我可以在像素着色器中修复所有这些。 但我需要非常快速地将24位转换为32位。 我对SIMD SSE操作并不十分熟悉,但从我粗略的一瞥来看,看起来我不能使用它们进行扩展,因为我的读写操作大小不一样。 有什么建议? 还是我按顺序按摩这个数据集? 这感觉非常愚蠢 – 我使用像素着色器进行并行处理,但在此之前我必须执行顺序逐像素操作。 我一定错过了一些明显的东西……

快速计算__m128i寄存器中的设置位数

我应该计算__m128i寄存器的设置位数。 特别是,我应该使用以下方法编写两个能够计算寄存器位数的函数。 寄存器的设定位总数。 寄存器的每个字节的设置位数。 是否存在可以完全或部分执行上述操作的内在function?

GNU C本机向量:如何广播标量,如x86的_mm_set1_epi16

我如何编写一个可移植的GNU C内置向量版本,它不依赖于x86 set1内在函数? typedef uint16_t v8su __attribute__((vector_size(16))); v8su set1_u16_x86(uint16_t scalar) { return (v8su)_mm_set1_epi16(scalar); // cast needed for gcc } 当然必须有一个更好的方式 v8su set1_u16(uint16_t s) { return (v8su){s,s,s,s, s,s,s,s}; } 我不想写一个用于广播单个字节的AVX2版本! 对于你想要分配给一个变量而不是仅仅用作二元运算符的操作数(这与gcc一起使用,见下文)的情况, 即使只是gcc-only或clang-only这个部分的答案也会很有趣 。 如果我想使用广播标量作为二元运算符的一个操作数,则可以使用gcc( 如手册中所述 ),但不能使用clang: v8su vecdiv10(v8su v) { return v / 10; } // doesn’t compile with clang 有了clang,如果我只针对x86并且只使用本机向量语法来让编译器为我生成模数乘法逆常数和指令 ,我可以写: v8su vecdiv_set1(v8su v) { […]

使用SSE最快地实现指数函数

我正在寻找在SSE元素上运行的指数函数的近似值。 即 – __m128 exp( __m128 x ) 。 我有一个快速但实际上准确度非常低的实现: static inline __m128 FastExpSse(__m128 x) { __m128 a = _mm_set1_ps(12102203.2f); // (1 << 23) / ln(2) __m128i b = _mm_set1_epi32(127 * (1 << 23) – 486411); __m128 m87 = _mm_set1_ps(-87); // fast exponential function, x should be in [-87, 87] __m128 mask = _mm_cmpge_ps(x, m87); […]

如何确定内存是否对齐?

我是使用SSE / SSE2指令优化代码的新手,直到现在我还没有走得太远。 据我所知,常见的SSE优化函数如下所示: void sse_func(const float* const ptr, int len){ if( ptr is aligned ) { for( … ){ // unroll loop by 4 or 2 elements } for( ….){ // handle the rest // (non-optimized code) } } else { for( ….){ // regular C code to handle non-aligned memory } } } […]

逻辑SSE内在函数之间有什么区别?

不同类型的逻辑SSE内在函数之间有什么区别吗? 例如,如果我们采用OR运算,有三个内在函数:_mm_or_ps,_mm_or_pd和_mm_or_si128所有这些都做同样的事情:计算其操作数的按位 OR。 我的问题: 使用一个或另一个内在(使用适当的类型转换)之间是否有任何区别。 在某些特定情况下,是否会有更长的执行等隐藏成本? 这些内在函数映射到三个不同的x86指令(por,orps,orpd)。 有没有人有任何想法为什么英特尔浪费宝贵的操作码空间的几个指令做同样的事情?

混合SSE整数/浮点SIMD指令时,是否会降低性能?

我最近以内在函数的forms使用了x86 SIMD指令(SSE1234)。 我发现令人沮丧的是SSE ISA有几个简单的指令,只能用于浮点数或仅用于整数,但理论上应该对两者都有相同的效果。 例如,float和double向量都有指令从地址( movhps , movhpd )加载更高的64位128位向量,但是没有这样的整数向量指令。 我的问题: 在整数向量上使用浮点指令时,有没有理由期望性能受到影响,例如使用movhps将数据加载到整数向量? 我写了几个测试来检查,但我认为他们的结果不可信。 编写一个正确的测试来探索这些事情的所有极端情况真的很难,特别是在这里最可能涉及指令调度时。 相关问题: 其他平凡相似的东西也有几个基本相同的指令。 例如,我可以使用por , orps或orpd按位OR。 任何人都可以解释这些附加说明的目的是什么? 我想这可能与应用于每条指令的不同调度算法有关。