loadu/lddqu 和赋值运算符有啥区别?
Posted
技术标签:
【中文标题】loadu/lddqu 和赋值运算符有啥区别?【英文标题】:What is the difference between loadu/lddqu and assignment operator?loadu/lddqu 和赋值运算符有什么区别? 【发布时间】:2020-04-29 14:21:00 【问题描述】:我正在使用SIMD向量进行一些计算,并好奇它们的区别,如下。
__m128i vector2 = vector1;
__m128i vector2 = _mm_loadu_si128(&vector1);
那么,以上两种说法有什么区别呢?
【问题讨论】:
第二个就像写x = *&y
- 它无缘无故地变得更加复杂。 (假设vector1
的类型为__m128i
。
【参考方案1】:
就像 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
等,但即使这样也不太正确,因为数据不需要与_Alignof(int)
、_Alignof(short)
、etc.,虽然 char
实际上在这里工作得很好。
正确的选择可能是提出参数void*
,但我猜英特尔想表明他们确实需要 16 字节的数据。 char mem_addr[16]
在 C99+ 中可以,但在 C++ 中不行,虽然 SSE2 与 C99 几乎同时出现,但许多编译器不支持 C99(MSVC 仍然不支持!)。
基本上,对于这个函数,忽略参数的类型并阅读描述。
【讨论】:
以上是关于loadu/lddqu 和赋值运算符有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章