我知道在AVX512中,你可以跨出1,2,4,8步长,但是如果我有一个任意的步幅,可以在10-1000之间?在编译时就知道了步幅。我明白了,指令不会成为瓶颈,内存可能会成为瓶颈。_mm512_set_ps是最有效的方法吗?
发布于 2021-07-14 00:00:14
大步步长为1,2,4,8
不,没有特别的支持;也许你在考虑ARM/ARM 64霓虹灯vld4 4路分离?
在x86中,您可以使用1,2,4或8作为vpgatherdd / vpgatherdps索引向量的比例因子,但是如果您只想要每2个元素,最好是手动洗牌(例如,_mm512_permutex2var_ps从2个输入向量中获取备用浮点数),在一个大负载下获得许多有用的元素,而不是每个元素访问一次缓存。
但在你的例子中,以10的最小步幅,最多2个元素将来自相同的16x32位512位矢量,而且每个向量的步幅更宽甚至不是一个。
因此,您可以在循环中使用vpgatherdps和_mm512_add_epi32(idx, _mm512_set1_epi32(16 * stride))。或更高版本,只需使用一个固定的索引向量并增加基本指针。,您可以使用_mm512_mullo_epi32(_mm512_setr_epi32(0,1,2,3,...,15), _mm512_set1_epi32(stride))生成该索引向量。因为浮点数是4个字节宽,所以在您的集合中使用4的缩放因子。
即使需要处理巨大的数组,增加指针而不是向量元素也避免了对64位索引的任何需求,同时也减少了向量uop的数量。(在当前CPU上使用512位向量时很有价值。)
IIRC,英特尔的优化手册有一个章节,关于跨越式负载和在手动收集和使用收集指令的权衡。收集指令变得相对更好,你的矢量越宽(2/时钟负载吞吐量,但只有1/时钟洗牌吞吐量对大多数洗牌),因此,特别是对512位向量,它很可能是胜利使用矢量洗牌。
https://stackoverflow.com/questions/68370267
复制相似问题