如何从SSE2 __m128i结构中提取字节?
我是SIMD内在函数的初学者,所以我会提前感谢大家的耐心等待.我有一个涉及无符号字节的绝对差异比较的应用程序(我正在使用灰度图像).
我尝试了AVX,更现代的SSE版本等,但最终决定SSE2似乎已经足够并且对个别字节的支持最多 – 如果我错了,请纠正我. 我有两个问题:第一,加载128位寄存器的正确方法是什么?我想我应该将加载的内在数据传递到128的倍数,但这样可以使用2D数组代码: greys = aligned_alloc(16,xres * sizeof(int8_t*)); for (uint32_t x = 0; x < xres; x++) { greys[x] = aligned_alloc(16,yres * sizeof(int8_t*)); } (上面的代码假设xres和yres是相同的,并且是2的幂).这会变成内存中的线性,不间断的块吗?那么,当我循环时,我可以继续将地址(递增128)传递给SSE2加载内在函数吗?或者像这样的2D阵列需要做些什么? 我的第二个问题:一旦我完成了所有的矢量处理,我如何从__m128i中提取修改后的字节?通过英特尔内在指南,将矢量类型转换为标量类型的指令很少见.我发现的最接近的是int _mm_movemask_epi8(__ m128i a),但我不太明白如何使用它. 哦,还有第三个问题 – 我假设_mm_load_si128只加载有符号字节?而且我找不到任何其他字节加载函数,所以我猜你应该从每个中减去128并稍后解释它? 我知道这些是SIMD专家的基本问题,但我希望这对像我这样的初学者有用.如果你认为我对应用程序的整个方法是错误的,或者我会更好地使用更现代的SIMD扩展,我很想知道.我只是想谦虚地警告我从未使用过装配,所有这些有点蠢蠢欲动的东西需要大量的解释才能帮助我. 不过,我很感激任何澄清. 如果它有所不同:我的目标是低功耗的i7 Skylake架构.但是,将应用程序运行在更旧的机器上也是很好的(因此SSE2). 解决方法
最不明显的问题是:
使用int64_t _mm_cvtsi128_si64x(__ m128i)或the low 32 bits with >随机移动矢量以使用低元素中所需的数据创建新的__m128i,并使用cvt内在函数(asm中的MOVD或MOVQ).
不,它是一个指向内存块的指针数组,引入了额外的间接级别与正确的2D阵列.不要那样做. 进行一次大型分配,并自己进行索引计算(使用array [x * yres y]). 是的,使用_mm_load_si128从中加载数据,或者如果需要从偏移量加载,则加载数据.
有符号或无符号不是字节的固有属性,它只是你如何解释这些位.您使用相同的加载内在函数来加载两个64位元素或128位位图. 使用适合您数据的内在函数.它有点像汇编语言:一切都只是字节,机器会用你的字节来做你所说的.您可以选择一系列指令/内在函数来产生有意义的结果. 整数加载内在函数采用__m128i *指针args,因此必须使用_mm_load_si128((const __m128i *)my_int_pointer)或类似的.这看起来像指针别名(例如,通过短*读取int数组),这是C和C中的未定义行为.但是,这就是英特尔表示您应该这样做的方式,因此任何实现英特尔内在函数的编译器都需要使其正常工作. gcc通过使用__attribute __((may_alias))定义__m128i来实现. 另请参阅Loading data for GCC’s vector extensions,其中指出您可以将英特尔内在函数用于GNU C本机向量扩展,并显示如何加载/存储. 要了解有关使用SSE的SIMD的更多信息,sse标记wiki中有一些链接,包括一些介绍/教程链接. x86标签wiki有一些很好的x86 asm / performance链接. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |