在GCC中编译SSE内在函数会产生错误

时间:2014-03-01 06:16:53

标签: gcc x86 intel sse simd

我的SSE代码在Windows平台上完全正常,但是当我在Linux上运行时,我遇到了很多问题。其中一个就是:

这只是我代码的示例说明:

int main(int ref, int ref_two)

{

 __128i a, b;

a.m128i_u8[0] = ref;

b.m128i_u8[0]  = ref_two;

.

.


.

.....

}

错误1:

  

错误:在非结构或联合的情况下请求成员'm128i_u8'

在这个线程中,它给出了使用适当的_mm_set_XXX内在函数而不是上述方法的解决方案,因为它只适用于Microsoft。 SSE intrinsics compiling MSDN code with GCC error?

我尝试了我在程序中替换set指令的线程中提到的上述方法,但它严重影响了我的应用程序的性能。

我的代码很庞大,需要在2000个地方更改。所以我在寻找更好的替代品,而不会影响我的应用程序的性能。

最近我收到了英特尔的这个链接,它说使用-fms-diaelect选项将它从Windows移植到Linux。

http://software.intel.com/sites/products/documentation/doclib/iss/2013/compiler/cpp-lin/GUID-7A69898B-BDBB-4AA9-9820-E4A590945903.htm

有人试过上述方法吗?有没有人找到将大型代码移植到Linux的解决方案?


@Paul,这是我的代码,我已经安排了一个计时器来测量两种方法所花费的时间,结果令人震惊。

代码1:115 ms(直接访问元素的Microsoft方法)

代码2:151 ms(使用设置指令)

当我在代码中使用set时,它耗费了36毫秒。

注意:如果我在我的单个指令中替换它需要36毫秒,并想象如果我在程序中将其替换2000次,我将获得性能降低。

这就是我寻找除设定指令之外的更好选择的原因

代码1:

__m128i array;
unsigned char* temp_src;
unsigned char* temp_dst;

for (i=0; i< 20; i++)

{

for (j=0; j< 1600; j+= 16)

 {
   Timerstart(&x);  
   array =  _mm_loadu_si128 ((__m128i *)(src));
   array.m128i_u8[0] =  36;
   y+ = Timerstop(x);
   _mm_store_si128( (__m128i *)temp_dst,array);

  }
 }

代码2:

 __m128i array;
 unsigned char* temp_src;
 unsigned char* temp_dst;

 for (i=0; i< 20; i++)
 {
 for (j=0; j< 1600; j+= 16)

 {



       Timerstart(&x);
       array = _mm_set_epi8(*(src+15),*(src+14),*(src+13),*(src+12),
                             *(src+11),*(src+10),*(src+9), *(src+8),
                         *(src+7), *(src+6), *(src+5), *(src+4),
                             *(src+3), *(src+2), *(src+1), 36 );
       y+ = Timerstop(x);

       _mm_store_si128( (__m128i *)temp_dst,array);

  }
}

1 个答案:

答案 0 :(得分:9)

您正在尝试使用非便携式Microsoft主义。坚持使用更便携的内在函数,例如_mm_set_epi8

 __128i a = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ref);

这适用于所有平台和编译器。

如果你看到性能问题那么可能是因为你在循环中做了一些低效的事情 - 没有看到实际的代码,尽管不可能提出任何关于提高代码效率的具体建议。

修改

通常有更有效的方法来加载具有值组合的向量,例如在您的示例中:

#include "smmintrin.h" // SSE4.1

for (...)
{
    for (...)
    {
        __m128i v = _mm_loadu_si128(0, (__m128i *)src); // load vector from src..src+15
        v = _mm_insert_epi8(v, 0, 36);                  // replace element 0 with constant `36`
       _mm_storeu_si128((__m128i *)dst, v);             // store vector at dst..dst+15
    }
}

这仅转换为3条指令。 (注意:如果你不能假设SSE4.1最小,那么_mm_insert_epi8可以用两个按位内在函数替换 - 这仍然比使用_mm_set_epi8更有效。