我的处理器是Intel 9700K。
我的__m128i
或__m256i
包含char
,short
或int
。我需要编写一个store
函数,该函数从头开始,从头开始或者从头到尾都忽略给定数量的元素。
对于ints
及更高版本,我使用_mm_maskstore_epi32
,尽管我想提高它的性能,但还不错。
但是对于较小的类型,我最初使用_mm_maskmoveu_si128
,它非常慢 -用我尝试的第一个代码将其替换为short
:使用_mm_maskstore_epi32
+在带有早午餐的标量中存储1个短整数,可将性能提高10倍。
所以,我的问题是:
_mm_maskstore_epi32
接受int*
。是否要求此int*
对齐4个字节?也许这是要求,它必须与16个字节对齐(对于256位寄存器为32个字节)?互联网对此并不十分清楚。我主要关心的是256位寄存器而不是128位寄存器。
UPD:我只在数组边界上使用蒙版。问题是-即使在1kb的阵列上,这也完全控制了我的性能(遍历1kb的数据并计算值并不像我在侧面处理存储那样重要)。我尝试了一个更简单的替代方法-只是为不被忽略的元素调用memcpy,它比我聪明的mask_store
骇客要快(可能是因为我不需要为mask_store
准备遮罩)。我可能需要类似专门的memcpy之类的东西来存储少于32个字节的数据。
有几种不同的处理数据大小的方法,而不是整个SIMD向量的倍数。这是三种可能性:
标量清理
屏蔽的最终SIMD迭代
_mm_maskstore_epi32
)可以避免这两个问题。重叠最终向量
n - vector_size
开始(即,最后两个向量将重叠)n >= vector_size
选择方法将取决于许多因素,但主要取决于n
的典型大小和范围。