错误:在c中转换用户定义的数据类型

时间:2017-05-02 10:14:48

标签: c gcc x86 sse simd

这是我的问题的简单视图,我想将浮点值转换为定义的类型v4si(我想使用SIMD操作进行优化。)请帮助将float / double值转换为定义的类型。

#include<stdio.h>

typedef double v4si __attribute__ ((vector_size (16)));

int main()
{
    double stoptime=36000;
    float x =0.5*stoptime;
    float * temp = &x;
    v4si a = ((v4si)x);   // Error: Incompatible data types
    v4si b;
    v4si *c;
    c = ((v4si*)&temp);   // Copies address of temp,           
    b = *(c);                   
    printf("%f\n" , b);      //    but printing (*c) crashes program
}

2 个答案:

答案 0 :(得分:3)

您不需要定义自定义SIMD矢量类型(v4si)或使用强制转换和类型惩罚 - 只需使用相应*intrin.h中提供的intrinsics即可标题,例如

#include <xmmintrin.h> // use SSE intrinsics 

int main(void)
{
    __m128 v;          // __m128 is the standard SSE vector type for 4 x float
    float x, y, z, w;

    v = _mm_set_ps(x, y, z, w);
                       // use intrinsic to set vector contents to x, y, z, w

    // ...

    return 0;
}

答案 1 :(得分:3)

您似乎正在使用GCC vector extensions。以下代码显示了如何使用向量扩展来执行广播,向量+标量,向量*标量,加载和存储。     #include

#if defined(__clang__)
typedef float v4sf __attribute__((ext_vector_type(4)));
#else
typedef float v4sf __attribute__ ((vector_size (16)));
#endif

void print_v4sf(v4sf a) { for(int i=0; i<4; i++) printf("%f ", a[i]); puts(""); }

int main(void) {
  v4sf a;
  //broadcast a scalar
  a = ((v4sf){} + 1)*3.14159f;  
  print_v4sf(a);

  // vector + scalar
  a += 3.14159f;
  print_v4sf(a);

  // vector*scalar
  a *= 3.14159f;
  print_v4sf(a);

  //load from array
  float data[] = {1, 2, 3, 4};
  a = *(v4sf*)data;
  //a = __builtin_ia32_loadups(data);

  //store to array
  float store[4];
  *(v4sf*)store = a;
  for(int i=0; i<4; i++) printf("%f ", store[i]); puts("");
}

Clang 4.0 ICC 17支持GCC向量扩展的子集。但是,它们都不支持GCC支持的vector + scalarvector*scalar操作。解决Clang的问题是使用Clang的OpenCL向量扩展。我不知道ICC的工作。 MSVC不支持我所知的任何类型的向量扩展。

即使GCC支持vector + scalarvector*scalar,你也无法做vector = scalar(但你可以使用Clang的OpenCL向量扩展)。相反,您可以使用this trick

a = ((v4sf){} + 1)*3.14159f;

我会这样做,因为Paul R建议使用内在函数,这些内在函数主要与四个主要的C / C ++编译器兼容:GCC,Clang,ICC和MSVC。

下面是每个编译器使用GCC向量扩展和Clang的OpenCL向量扩展支持的内容表。

                                gcc  g++  clang  icc   OpenCL
unary operations                
[]                              yes  yes  yes    yes   yes
+, –                            yes  yes  yes    yes   yes
++, --                          yes  yes  no     no    no
~                               yes  yes  yes    yes   yes
!                               no   yes  no     no    yes 

binary vector op vector         
+,–,*,/,%                       yes  yes  yes    yes   yes    
&,|,^                           yes  yes  yes    yes   yes
>>,<<                           yes  yes  yes    yes   yes
==, !=, >, <, >=, <=            yes  yes  yes    yes   yes
&&, ||                          no   yes  no     no    yes

binary vector op scalar         
+,–,*,/,%                       yes  yes  no     no    yes
&,|,^                           yes  yes  no     no    yes
>>,<<                           yes  yes  no     no    yes
==, !=, >, <, >=, <=            yes  yes  no     no    yes                      
&&, ||                          no   yes  no     no    yes

assignment
vector = vector                 yes  yes  yes    yes   yes
vector = scalar                 no   no   no     no    yes                                              

ternary operator
?:                              no   yes  no     no    ?

我们看到Clang和ICC不支持GCC的vector operator scalar操作。 C ++模式下的GCC支持除vector = scalar之外的所有内容。 Clang的OpenCL向量扩展支持除三元运算符之外的所有内容。 Clang的文档声称它确实如此,但我没有让它工作。 C模式下的GCC附加不支持二进制逻辑运算符或三元运算符。