Это более простое представление о моей проблеме. Я хочу преобразовать значение float в определенный тип v4si (я хочу использовать SIMD-операцию для оптимизации.) Пожалуйста, помогите преобразовать значение float/double в определенный тип.
Ответ 1
Вам не нужно определять собственный тип вектора SIMD (v4si
) или запутываться с помощью прикладов и пингом типа - просто используйте предоставленный intrinsics в соответствующем заголовке *intrin.h
, например
#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;
}
Ответ 2
Похоже, вы используете 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. Однако ни одна из них не поддерживает операции vector + scalar
или vector*scalar
, которые поддерживает GCC. Работа для Clang заключается в использовании расширений Vector Clang OpenCL. Я не знаю, как работать в ICC. MSVC не поддерживает любое расширение вектора, о котором я знаю.
С GCC, даже если он поддерживает vector + scalar
и vector*scalar
, вы не можете сделать vector = scalar
(но вы можете использовать расширения Clang OpenCL). Вместо этого вы можете использовать этот трюк.
a = ((v4sf){} + 1)*3.14159f;
Я бы сделал, как предлагает Paul R, и использует встроенные функции, которые в основном совместимы с четырьмя основными компиляторами 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 yes yes 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
. GCC в режиме С++ поддерживает все, кроме vector = scalar
. Расширения Clang OpenCL поддерживают все, кроме трехмерного оператора. Документация Clang заявляет, что она работает, но я не могу заставить ее работать. Дополнительно GCC в режиме C не поддерживает двоичные логические операторы или тройной оператор.