_mm_shuffle_epi8 上的一般保护故障
Posted
技术标签:
【中文标题】_mm_shuffle_epi8 上的一般保护故障【英文标题】:General protection fault on _mm_shuffle_epi8 【发布时间】:2014-02-07 12:53:42 【问题描述】:我在 C 中有一个函数,原型为 void f(__m128i *x)
。在这个函数中,我现在调用_mm_shuffle_epi8(*x, MASK)
,其中MASK
是一些常量__m128i
类型。当我运行代码时,我遇到了一个分段错误,而 Valgrind 显示它实际上是发生在这一行的一般保护错误。
这可能是什么原因,我该如何解决?
小型工作示例:
#include <wmmintrin.h>
#include <smmintrin.h>
#define BSWAP_MASK _mm_set_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
#define ALIGN(n) __attribute__ ((aligned(n)))
static inline void g(const unsigned char *in, unsigned char *out)
__m128i tmp = _mm_load_si128 ((__m128i*)in);
_mm_store_si128((__m128i*)out, tmp);
void f(__m128i *res)
g((unsigned char*)&res, (unsigned char*)&res);
*res = _mm_shuffle_epi8(*res, BSWAP_MASK);
int main()
ALIGN(16) __m128i x = _mm_set_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
f(&x);
【问题讨论】:
内存在x
16字节对齐吗?
是16字节对齐的
如果您可以发布一个小的、可重复的示例,我们可以用来复制,我们会提供帮助。
是的,我正在尝试,但我的小例子不会重现坏东西..
如果(x)
指向单个__m128
而不是一个数组,那么按值传递,按值返回不是更容易吗?可能使用 SSE 寄存器来传递参数和返回值,即使没有内联。
【参考方案1】:
正如怀疑的那样,您遇到了对齐问题。
如果你没有正确对齐你的数据,或者使用函数在未对齐的地址加载和存储,结果就是崩溃。
如果您想使用未对齐的地址,那么这可以解决问题:
static inline void g(const unsigned char *in, unsigned char *out)
//__m128i tmp = _mm_load_si128 ((__m128i*)in);
__m128i tmp = _mm_loadu_si128 ((__m128i*)in);
//_mm_store_si128((__m128i*)out, tmp);
_mm_storeu_si128((__m128i*)out, tmp);
至于为什么链接器无法使该变量正确对齐,请参阅Are stack variables aligned by the GCC __attribute__((aligned(x)))? 和那里的答案。
如果你在linux上,你可以使用posix_memalign()函数。
【讨论】:
以上是关于_mm_shuffle_epi8 上的一般保护故障的主要内容,如果未能解决你的问题,请参考以下文章