C

时间:2015-05-20 16:17:11

标签: c sse

运行以下简短C代码的编译时出现Segmentation故障:

#include <pmmintrin.h>
#include <stdio.h>
#include <stdlib.h>
#define VALUE 4242

typedef short int Type;
void threshold(Type *dst, const Type *src, int len)
{
  short int i, N=16;
  short int checkval[] = { VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE };

  const short int* __attribute__ ((aligned (16))) line1;

  __m128i v1, v2, v3:
  v2 = _mm_loadu_si128((__m128i*) checkval );

  for(i = 0; i < len; i+=N)
    {
      line1 = src + N*i;
      //Thisline                                                                                                                                     
      v1 = _mm_loadu_si128((__m128i*) line1 );
      v3 = _mm_cmpgt_epi16( v1, v2 );

      _mm_storeu_si128((__m128i*) (dst + N*i), v3 );

    }
  return;
}

int main()
{
  int N = 1024;
  Type dst[N], src[N];
  int i;
  for(i = 0; i < N; i++)
    src[i] = rand()%VALUE;

  threshold(dst, src, N);
  return 0;
}

我很确定“这条线”给我带来问题,但我无法判断问题是否是由于line1不适合__m128i或其他错误引起的。

作为一个子问题 - 我试图对齐line1中的元素,函数_mm_load_si128更合适(我试过两个,但我无法避免这个错误)。

2 个答案:

答案 0 :(得分:1)

threshold

short int i, N=16;

应该是:

short int i, N=8;

这是因为每个向量有8个short int元素,并且指针算法会考虑元素的大小(我的猜测是你假设你需要使用16个字节作为a的大小矢量?)。

答案 1 :(得分:1)

在评论对齐之前,请考虑到houssam的评论和Paul's answer,腐败来自这里肯定。

现在,src可能不是16字节对齐的。参考此 post about alignment on static arrayssrc至少在2字节字上对齐,但可能不在16字节地址上。

因此,即使将line1声明为对齐指针,for循环第一行的赋值也可能会破坏此约束。

考虑在__attribute__ ((aligned(8)))声明中添加srcmain()内)。

修改

在我的评论之后要明确:PaulR在他的回答中指出了一个初始根本原因,类型__m128的大小为8个短整数而不是16个。另一个失败的根本原因是问题索引i。通过撰写line1 = src+i*Ni+=Nsrc的偏移实际上在每次迭代时增加N*N

所以你有两个独家解决方案:

  • 更改索引i 的增量和索引的结束限制:for(i = 0; i < len/N; i++);保持原样。
  • 或更改src dst的偏移 line1 = src + i;_mm_storeu_si128((__m128i*) (dst + i), v3 );