C++ SSE:存储到数组后的未定义行为
C++ SSE: Undefined behavior after storing to an array
我正在使用 SSE 指令 _mm_loadu_si128
从 2 个未对齐的向量 vec1
和 vec2
读取 uint64_t
整数,该指令从对齐和未对齐的内存中读取数据。然后我进行按位和运算,然后使用 _mm_storeu_si128
将结果存储到未对齐的内存中。存储的目标是一个名为 arr1
的数组。似乎在商店之前,我可以访问 arr1
,但是在商店访问 arr1
之后出现未定义的行为(有时是段错误)。
#include <vector>
#include <emmintrin.h>
#include <nmmintrin.h>
#include <chrono>
#include <smmintrin.h>
#include <iostream>
int main()
{
std::vector<uint64_t> vec1(200);
std::vector<uint64_t> vec2(200,1);
std::vector<uint64_t> *p_vec1 = &vec1;
std::vector<uint64_t> *p_vec2 = &vec2;
int total_bits = 0;
int k = 0;
for(; k < 100; k+=2){
__m128i* ptr1 = (__m128i*) (p_vec1 + k);
__m128i* ptr2 = (__m128i*) (p_vec2 + k);
__m128i val1_4 = _mm_loadu_si128(ptr1);
__m128i val2_4 = _mm_loadu_si128(ptr2);
uint64_t arr1[2] = {0,0};
std::cout << "val1 " << arr1[0] << std::endl;
_mm_storeu_si128((__m128i*) arr1, _mm_and_si128(val1_4, val2_4)); // after storing into arr1, Accessing arr1 gives undefined behavior
std::cout << "val2 " << arr1[0] << std::endl; // This should only output 0s but instead outputs random numbers
total_bits += __builtin_popcountll(arr1[0]);
}
}
是_mm_storeu_si128
"changing the structure" of arr1
,难道是我进店后无法访问的原因吗?
std::vector<uint64_t> *p_vec1 = &vec1;
std::vector<uint64_t> *p_vec2 = &vec2;
绝对不是您想要的。这并不意味着 p_vec1
指向向量中的元素,而是指向向量本身。您稍后执行 (__m128i*) (p_vec1 + k)
读取是未定义的行为: p_vec1 + 1
不指向向量的第二个值;它指向 vec1
之后的向量(这没有任何意义)。
您可能想要以下内容:
uint64_t *p_vec1 = vec1.data();
uint64_t *p_vec2 = vec2.data();
这样 p_vec1
和 p_vec2
都指向向量的内容。
我正在使用 SSE 指令 _mm_loadu_si128
从 2 个未对齐的向量 vec1
和 vec2
读取 uint64_t
整数,该指令从对齐和未对齐的内存中读取数据。然后我进行按位和运算,然后使用 _mm_storeu_si128
将结果存储到未对齐的内存中。存储的目标是一个名为 arr1
的数组。似乎在商店之前,我可以访问 arr1
,但是在商店访问 arr1
之后出现未定义的行为(有时是段错误)。
#include <vector>
#include <emmintrin.h>
#include <nmmintrin.h>
#include <chrono>
#include <smmintrin.h>
#include <iostream>
int main()
{
std::vector<uint64_t> vec1(200);
std::vector<uint64_t> vec2(200,1);
std::vector<uint64_t> *p_vec1 = &vec1;
std::vector<uint64_t> *p_vec2 = &vec2;
int total_bits = 0;
int k = 0;
for(; k < 100; k+=2){
__m128i* ptr1 = (__m128i*) (p_vec1 + k);
__m128i* ptr2 = (__m128i*) (p_vec2 + k);
__m128i val1_4 = _mm_loadu_si128(ptr1);
__m128i val2_4 = _mm_loadu_si128(ptr2);
uint64_t arr1[2] = {0,0};
std::cout << "val1 " << arr1[0] << std::endl;
_mm_storeu_si128((__m128i*) arr1, _mm_and_si128(val1_4, val2_4)); // after storing into arr1, Accessing arr1 gives undefined behavior
std::cout << "val2 " << arr1[0] << std::endl; // This should only output 0s but instead outputs random numbers
total_bits += __builtin_popcountll(arr1[0]);
}
}
是_mm_storeu_si128
"changing the structure" of arr1
,难道是我进店后无法访问的原因吗?
std::vector<uint64_t> *p_vec1 = &vec1;
std::vector<uint64_t> *p_vec2 = &vec2;
绝对不是您想要的。这并不意味着 p_vec1
指向向量中的元素,而是指向向量本身。您稍后执行 (__m128i*) (p_vec1 + k)
读取是未定义的行为: p_vec1 + 1
不指向向量的第二个值;它指向 vec1
之后的向量(这没有任何意义)。
您可能想要以下内容:
uint64_t *p_vec1 = vec1.data();
uint64_t *p_vec2 = vec2.data();
这样 p_vec1
和 p_vec2
都指向向量的内容。