Reputation: 71
This is a simpler view of my Problem, I want to convert a float value into defined type v4si (I want to use SIMD Operation for optimization.) Please help to convert float/double value to a defined type.
#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
}
Upvotes: 2
Views: 925
Reputation: 33669
You appear to be using GCC vector extensions. The following code shows how to do broadcasts, vector + scalar, vector*scalar, loads and stores using 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 and ICC 17 support a subset of the GCC vector extensions. However, neither of them support vector + scalar
or vector*scalar
operations which GCC supports. A work around for Clang is to use Clang's OpenCL vector extensions. I don't know of a work around for ICC. MSVC does not support any kind of vector extension that I am aware of.
With GCC even though it supports vector + scalar
and vector*scalar
you cannot do vector = scalar
(but you can with Clang's OpenCL vector extensions). Instead you can use this trick.
a = ((v4sf){} + 1)*3.14159f;
I would do as Paul R suggests and use intrinsics which are mostly compatible with the four major C/C++ compilers: GCC, Clang, ICC, and MSVC.
Here is a table of what is supported by each compiler using GCC's vector extensions and Clang's OpenCL vector extensions.
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 ?
We see that Clang and ICC do not support GCC's vector operator scalar
operations. GCC in C++ mode supports everything but vector = scalar
. Clang's OpenCL vector extensions support everything except maybe the ternary operator. Clang's documentation claims it does but I don't get it to work. GCC in C mode additional does not support binary logical operators or the ternary operator.
Upvotes: 3
Reputation: 212979
You don't need to define a custom SIMD vector type (v4si
) or mess around with casts and type punning - just use the provided intrinsics in the appropriate *intrin.h
header, e.g.
#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;
}
Upvotes: 3