Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ SIMD m256i到m256d转换结果_C++_X86_Simd_Intrinsics_Avx2 - Fatal编程技术网

C++ SIMD m256i到m256d转换结果

C++ SIMD m256i到m256d转换结果,c++,x86,simd,intrinsics,avx2,C++,X86,Simd,Intrinsics,Avx2,我试图将SIMD整数变量转换为双精度变量。但我看不出这次行动会有什么结果。 例如: 由于此操作,我的temp2中的成员是什么 此操作的结果是,temp2将包含垃圾。例如,第一条双车道将为4.0146351468550722e-305 这是故意的\u mm256\u castsi256\u pd内在函数不转换值,它只将寄存器中的位重新解释为双精度 如果要在寄存器中使用这些双常量,只需使用\u mm256\u setr\u pd固有值: // Set double values to the con

我试图将SIMD整数变量转换为双精度变量。但我看不出这次行动会有什么结果。 例如:


由于此操作,我的temp2中的成员是什么

此操作的结果是,temp2将包含垃圾。例如,第一条双车道将为4.0146351468550722e-305

这是故意的<代码>\u mm256\u castsi256\u pd内在函数不转换值,它只将寄存器中的位重新解释为双精度

如果要在寄存器中使用这些双常量,只需使用
\u mm256\u setr\u pd
固有值:

// Set double values to the constants
__m256d temp2 = _mm256_setr_pd( 12345678, 12333333, 12344444, 12355555 );
或者,如果这些值不是常量,请使用_mm256_cvtepi32_pd intrinsive,下面是一个完整的示例:

alignas( 32 ) int arr[ 8 ] = { 12345678, 12333333, 12344444, 12355555,
    12366666, 12377777, 12388888, 12399999 };
__m256i integers = _mm256_load_si256( ( const __m256i* ) &arr );
// Convert first 4 int32 values to doubles
__m256d lowDoubles = _mm256_cvtepi32_pd( _mm256_castsi256_si128( integers ) );
// Convert last 4 values to doubles
__m256d highDoubles = _mm256_cvtepi32_pd( _mm256_extracti128_si256( integers, 1 ) );
这实际上将转换值,而不是位转换

AVX寄存器保存256位数据。这是
\uuuum256i
类型中的8个int32值,是
\uuum256
数据类型中的8个浮点值,但在
\uuuum256d
类型中只有4个双值


另外,您的代码中也存在对齐错误,最好的修复方法是在
int-arr[8]

之前添加
alignas(32)
。由于此操作,temp2将包含垃圾。例如,第一条双车道将为4.0146351468550722e-305

这是故意的<代码>\u mm256\u castsi256\u pd内在函数不转换值,它只将寄存器中的位重新解释为双精度

如果要在寄存器中使用这些双常量,只需使用
\u mm256\u setr\u pd
固有值:

// Set double values to the constants
__m256d temp2 = _mm256_setr_pd( 12345678, 12333333, 12344444, 12355555 );
或者,如果这些值不是常量,请使用_mm256_cvtepi32_pd intrinsive,下面是一个完整的示例:

alignas( 32 ) int arr[ 8 ] = { 12345678, 12333333, 12344444, 12355555,
    12366666, 12377777, 12388888, 12399999 };
__m256i integers = _mm256_load_si256( ( const __m256i* ) &arr );
// Convert first 4 int32 values to doubles
__m256d lowDoubles = _mm256_cvtepi32_pd( _mm256_castsi256_si128( integers ) );
// Convert last 4 values to doubles
__m256d highDoubles = _mm256_cvtepi32_pd( _mm256_extracti128_si256( integers, 1 ) );
这实际上将转换值,而不是位转换

AVX寄存器保存256位数据。这是
\uuuum256i
类型中的8个int32值,是
\uuum256
数据类型中的8个浮点值,但在
\uuuum256d
类型中只有4个双值

另外,代码中也存在对齐错误,最好的修复方法是在
int-arr[8]之前添加
alignas(32)
temp2
中的成员将是:

{4.014635e-305, 4.062922e-305, 4.111209e-305, 4.159495e-305}
如何获取这些值 只需将SIMD数据写入一个
double
数组中,并将其打印出来即可

#include <stdio.h>
#include <immintrin.h>

int main(void) {
    int hoge[4]; /* hack that worked on tested environment to avoid Segmentation Fault */
    double result[4];
    int i;

    int arr[8]={12345678,12333333,12344444,12355555,12366666,12377777,12388888,12399999};
    __m256i temp = _mm256_load_si256((__m256i *) arr);
    __m256d temp2 = _mm256_castsi256_pd (temp);

    _mm256_storeu_pd(result, temp2);
    for (i = 0; i < 4; i++) printf("result[%d] = %.6e (%.15a)\n", i, result[i], result[i]);
    return 0;
}
您可以通过将SIMD数据写入
double
数组

当将未对齐32字节的地址传递到时,可能会生成异常,因此您应该进行对齐。实际上,Wandbox上出现了分段错误,因此我插入了虚拟数组
hoge
,以进行对齐

获得这些值的原因 实际上只是复制字节并更改其解释

假设使用小尾端且
int
为4字节长, 在字节寻址存储器中,
arr
中的数据如下:

data in arr[8]:
|   12345678|   12333333|   12344444|   12355555|   12366666|   12377777|   12388888|   12399999|
byte data in arr[8] (in little endian):
|4e 61 bc 00|15 31 bc 00|7c 5c bc 00|e3 87 bc 00|4a b3 bc 00|b1 de bc 00|18 0a bd 00|7f 35 bd 00|
data seen as 64-bit hex:
|     0x00bc311500bc614e|     0x00bc87e300bc5c7c|     0x00bcdeb100bcb34a|     0x00bd357f00bd0a18|
然后,假设在
double
中使用64位,64位数据由1位符号、11位指数和52位有效位组成

以第一个元素
0x00bc311500bc614e
为例,符号位为
0
(加/零),指数为
0x00b
(11-1023=-1012),有效位为
0xc311500bc614e

这与上面示例代码中通过
%.15a
打印的内容相匹配。 (额外打印两个
0
s,因为指定了打印15位数字,而只对13位数字的数据进行了重新排序,因此剩余部分用
0
填充) 其他元素也与此匹配。

简短回答
temp2
中的成员将是:

{4.014635e-305, 4.062922e-305, 4.111209e-305, 4.159495e-305}
如何获取这些值 只需将SIMD数据写入一个
double
数组中,并将其打印出来即可

#include <stdio.h>
#include <immintrin.h>

int main(void) {
    int hoge[4]; /* hack that worked on tested environment to avoid Segmentation Fault */
    double result[4];
    int i;

    int arr[8]={12345678,12333333,12344444,12355555,12366666,12377777,12388888,12399999};
    __m256i temp = _mm256_load_si256((__m256i *) arr);
    __m256d temp2 = _mm256_castsi256_pd (temp);

    _mm256_storeu_pd(result, temp2);
    for (i = 0; i < 4; i++) printf("result[%d] = %.6e (%.15a)\n", i, result[i], result[i]);
    return 0;
}
您可以通过将SIMD数据写入
double
数组

当将未对齐32字节的地址传递到时,可能会生成异常,因此您应该进行对齐。实际上,Wandbox上出现了分段错误,因此我插入了虚拟数组
hoge
,以进行对齐

获得这些值的原因 实际上只是复制字节并更改其解释

假设使用小尾端且
int
为4字节长, 在字节寻址存储器中,
arr
中的数据如下:

data in arr[8]:
|   12345678|   12333333|   12344444|   12355555|   12366666|   12377777|   12388888|   12399999|
byte data in arr[8] (in little endian):
|4e 61 bc 00|15 31 bc 00|7c 5c bc 00|e3 87 bc 00|4a b3 bc 00|b1 de bc 00|18 0a bd 00|7f 35 bd 00|
data seen as 64-bit hex:
|     0x00bc311500bc614e|     0x00bc87e300bc5c7c|     0x00bcdeb100bcb34a|     0x00bd357f00bd0a18|
然后,假设在
double
中使用64位,64位数据由1位符号、11位指数和52位有效位组成

以第一个元素
0x00bc311500bc614e
为例,符号位为
0
(加/零),指数为
0x00b
(11-1023=-1012),有效位为
0xc311500bc614e

这与上面示例代码中通过
%.15a
打印的内容相匹配。 (额外打印两个
0
s,因为指定了打印15位数字,而只对13位数字的数据进行了重新排序,因此剩余部分用
0
填充)
其他元素也像这样匹配。

操作
\u mm256\u castsi256\u pd
实际上什么都不做,它是一种重新解释-相当于:

  int v_i;
  double d_i = *((double*)(int*)&v_i).
使用
\uuuum256d\umm256\ucvtepi32\upd(\uuuum128i a)
,因为它实际上将4个整数转换为4个双精度

alignas(16) int arr[4]={12345678,12333333,12344444,12355555};
__m128i temp = _mm_load_si128((__m128i *) arr);
__m256d temp2 = _mm256_cvtepi32_pd(temp);

注意:加载操作要求地址正确对齐。否则,请使用未对齐的版本
\u mm\u loadu\u si128
\u mm256\u loadu\u si256
;虽然未对齐的版本速度较慢。

操作
\u mm256\u castsi256\u pd
实际上什么都不做,但它是一种重新解释-相当于:

  int v_i;
  double d_i = *((double*)(int*)&v_i).
使用
\uuuum256d\umm256\ucvtepi32\upd(\uuuum128i a)
,因为它实际上将4个整数转换为4个双精度

alignas(16) int arr[4]={12345678,12333333,12344444,12355555};
__m128i temp = _mm_load_si128((__m128i *) arr);
__m256d temp2 = _mm256_cvtepi32_pd(temp);

注意:加载操作要求地址正确对齐。否则,请使用未对齐的版本
\u mm\u loadu\u si128
\u mm256\u loadu\u si256
;认为未对齐的版本比较慢。

为什么使用可能导致故障的
\u mm256\u loadu\u si256
,而不是
\u mm256\u loadu\u si25