loadu/lddqu 和赋值运算符有什么区别?
What is the difference between loadu/lddqu and assignment operator?
我正在使用SIMD vector做一些计算,好奇它们的区别,如下。
__m128i vector2 = vector1;
__m128i vector2 = _mm_loadu_si128(&vector1);
那么,以上两种说法有什么不同呢?
正如 Peter Cordes 在他的评论中所说,如果 vector1
真的是 __m128i
,那就太复杂了。
然而,这不是 _mm_loadu_si128
的用例。虽然争论的类型是 __m128i const*
,但实际上更多的是缺乏好的选择和糟糕的决定。
_mm_loadu_si128
的真正意思是将任意 16 字节的数据加载到向量寄存器中。如果你想加载已经对齐到 16 字节边界的数据,你应该使用 _mm_load_si128
代替。如果您的数据未与 16 字节边界对齐,则它不是 真正的 和 __m128i
,因此参数类型充其量只是误导。
英特尔(或任何人)选择使用 __m128i const*
的原因尚不完全清楚,但老实说,没有太多好的选择。 int const*
没有意义,因为我们要加载的并不总是 32 位有符号整数。他们本可以制作 _mm_loadu_epi8
、_mm_loadu_epi16
、_mm_loadu_epi32
等,但即使那样也不太正确,因为数据不需要与 [=22= 对齐]、_Alignof(short)
、等,尽管char
实际上在这里工作得很好。
正确的选择可能是提出论点 void*
,但我猜英特尔想表明他们确实需要 16 字节的数据。 char mem_addr[16]
在 C99+ 中可以,但在 C++ 中不行,虽然 SSE2 与 C99 大约同时出现,但许多编译器不支持 C99(MSVC 仍然不支持!)。
基本上,对于这个函数,忽略参数的类型并阅读描述。
我正在使用SIMD vector做一些计算,好奇它们的区别,如下。
__m128i vector2 = vector1;
__m128i vector2 = _mm_loadu_si128(&vector1);
那么,以上两种说法有什么不同呢?
正如 Peter Cordes 在他的评论中所说,如果 vector1
真的是 __m128i
,那就太复杂了。
然而,这不是 _mm_loadu_si128
的用例。虽然争论的类型是 __m128i const*
,但实际上更多的是缺乏好的选择和糟糕的决定。
_mm_loadu_si128
的真正意思是将任意 16 字节的数据加载到向量寄存器中。如果你想加载已经对齐到 16 字节边界的数据,你应该使用 _mm_load_si128
代替。如果您的数据未与 16 字节边界对齐,则它不是 真正的 和 __m128i
,因此参数类型充其量只是误导。
英特尔(或任何人)选择使用 __m128i const*
的原因尚不完全清楚,但老实说,没有太多好的选择。 int const*
没有意义,因为我们要加载的并不总是 32 位有符号整数。他们本可以制作 _mm_loadu_epi8
、_mm_loadu_epi16
、_mm_loadu_epi32
等,但即使那样也不太正确,因为数据不需要与 [=22= 对齐]、_Alignof(short)
、等,尽管char
实际上在这里工作得很好。
正确的选择可能是提出论点 void*
,但我猜英特尔想表明他们确实需要 16 字节的数据。 char mem_addr[16]
在 C99+ 中可以,但在 C++ 中不行,虽然 SSE2 与 C99 大约同时出现,但许多编译器不支持 C99(MSVC 仍然不支持!)。
基本上,对于这个函数,忽略参数的类型并阅读描述。