Tag: sse

使用SSE索引到数组

假设我有一个数组: uint8_t arr[256]; 和一个元素 __m128i x 包含16个字节, x_1, x_2, … x_16 我想有效地填充一个新的__m128i元素 __m128i y 使用arr中的值取决于x的值,这样: y_1 = arr[x_1] y_2 = arr[x_2] . . . y_16 = arr[x_16] 实现此目的的命令实质上是从非连续的一组存储器位置加载寄存器。 我看到这样一个命令的文档有一个痛苦的模糊记忆,但现在找不到它。 它存在吗? 在此先感谢您的帮助。

一个更好的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 […]

用于SSE类型的战俘

我使用SSE类型进行了一些显式向量化计算,例如__m128 (在xmmintrin.h等中定义),但现在我需要将向量的所有元素提升到某个(相同)幂,即理想情况下我想要像__m128 _mm_pow_ps(__m128, float) ,遗憾的是不存在。 围绕这个的最佳方法是什么? 我可以存储向量,在每个元素上调用std::pow ,然后重新加载它。 这是我能做的最好的吗? 编译器如何在自动矢量化代码时实现对std::pow的调用,否则代码可以很好地实现矢量化? 有没有提供有用function的库? (请注意, 这个问题与重复无关,当然没有一个有用的答案。)

寻找用于非立即移位值的sse 128位移位操作

内部_mm_slli_si128将在128位寄存器的左侧进行逻辑移位,但仅限于立即移位值,并按字节而不是位移位。 我可以使用像_mm_sll_epi64或_mm_sll_epi32这样的内部函数在__m128i寄存器中向左移位一组值,但这些值不带“溢出”位。 对于N位的移位想象我可以做类似的事情: _mm_sll_epi64 _mm_srr_epi64 (对于我想要携带的位:将它们移动到低位) 洗牌srr结果 或者这些在一起。 (但可能还必须包括N相对于64的检查)。 有没有更好的办法?

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

我写了函数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 […]

SSE指令MOVSD(扩展:x86上的浮点标量和向量运算,x86-64)

我莫名其妙地被MOVSD汇编指令搞糊涂了。 我写了一些计算一些矩阵乘法的数字代码,简单地使用没有SSE内在函数的普通C代码。 我甚至没有包含用于编译的SSE2内在函数的头文件。 但是当我检查汇编器输出时,我看到: 1)使用128位向量寄存器XMM; 2)调用SSE2指令MOVSD。 我知道MOVSD基本上是在单双精度浮点上运行。 它只使用XMM寄存器的低64位并设置高64位0.但我只是不明白两件事: 1)我从不给编译器任何使用SSE2的提示。 另外,我使用GCC而不是英特尔编译器。 据我所知,intel编译器会自动寻找矢量化的机会,但GCC不会。 那么GCC如何知道使用MOVSD? 或者,这个x86指令是否早在SSE指令集之前就已存在,而SSE2中的_mm_load_sd()内在函数只是为了提供向后兼容性来使用XMM寄存器进行标量计算? 2)为什么编译器不使用其他浮点寄存器,无论是80位浮点堆栈还是64位浮点寄存器? 为什么必须使用XMM寄存器(通过设置高64位0并基本上浪费该存储)来收费? XMM是否提供更快的访问? 顺便说一句,我有另外一个关于SSE2的问题。 我只是看不到_mm_store_sd()和_mm_storel_sd()之间的区别。 两者都将较低的64位值存储到地址。 有什么不同? 性能差异?? 对齐差异?? 谢谢。 更新1: 好的,显然当我第一次提出这个问题时,我缺乏一些关于CPU如何管理浮点运算的基本知识。 所以专家倾向于认为我的问题是无意义的。 由于我没有包括最短的样本C代码,人们可能会认为这个问题也很模糊。 在这里,我将提供一个回答作为答案,希望对任何不清楚现代CPU上的浮点运算的人都有用。

重叠数组的总和,自动矢量化和限制

Arstechnia最近有一篇文章为什么一些编程语言比其他语言更快 。 它比较了Fortran和C,并提到了求和数组。 在Fortran中,假设数组不重叠,因此可以进一步优化。 在C / C ++中,指向相同类型的指针可能会重叠,因此通常不能使用此优化。 但是,在C / C ++中,可以使用restrict或__restrict关键字告诉编译器不要假设指针重叠。 所以我开始研究自动矢量化。 以下代码在GCC和MSVC中进行矢量化 void dot_int(int *a, int *b, int *c, int n) { for(int i=0; i<n; i++) { c[i] = a[i] + b[i]; } } 我使用和不使用重叠数组测试了它,它得到了正确的结果。 但是,我使用SSE手动向量化循环的方式不能处理重叠数组。 int i=0; for(; i<n-3; i+=4) { __m128i a4 = _mm_loadu_si128((__m128i*)&a[i]); __m128i b4 = _mm_loadu_si128((__m128i*)&b[i]); __m128i c4 = […]

快速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?

GCC SSE代码优化

这篇文章与我几天前发布的另一篇文章密切相关。 这一次,我编写了一个简单的代码,它只添加了一对元素数组,将结果乘以另一个数组中的值并将其存储在第四个数组中,所有变量浮点数都是双精度类型。 我制作了两个版本的代码:一个是SSE指令,使用调用而另一个没有它我然后用gcc和-O0优化级别编译它们。 我在下面写下: // SSE VERSION #define N 10000 #define NTIMES 100000 #include #include #include #include double a[N] __attribute__((aligned(16))); double b[N] __attribute__((aligned(16))); double c[N] __attribute__((aligned(16))); double r[N] __attribute__((aligned(16))); int main(void){ int i, times; for( times = 0; times < NTIMES; times++ ){ for( i = 0; i <N; i+= 2){ __m128d mm_a = _mm_load_pd( […]