![]() |
1
6
您可以替换转换epi16->epi32->浮点和乘的标准方法
这是因为除数是2的幂,所以手动组合浮点表示不同的指数。 多亏了@petercordes,这里有一个优化的avx2版本,使用xor在翻转整数值的符号位的同时设置32位浮点的高位字节。fp sub将尾数的低位转换为正确的fp值:
看到它
on the Godbolt compiler explorer with gcc and clang
;在Skylake i7-6700K上,一个2048元素的高速缓存循环需要大约360个时钟周期,与执行标准符号扩展/转换/乘法(循环展开量相似)的@wim版本的速度(到测量误差内)相同。由@petercordes在linux下测试
的异或
奇怪的是,gcc和clang更喜欢用
这里有一个SSE2版本,它分别执行有符号/无符号翻转,而不设置32位FP位模式的高2字节。
我们在用一个
使用演示: https://ideone.com/b8BfJd
如果您的输入是无符号短
, the
这个可以
此外,对于纯SSE解决方案,可以简单地使用
我没有对任何解决方案进行基准测试(也没有检查理论吞吐量或延迟) |
![]() |
2
5
对于avx2,不需要分别转换高、低部件:
这个编译得很好 on the Godbolt compiler explorer ,使用L1D缓存中的热输入/输出和对齐的输入/输出数组,在Skylake i7-6700k上以约360个时钟周期转换2048个元素的数组(在重复循环中测试)。这是每个元素大约0.18个周期,或者每个时钟周期大约5.7个转换。或每个向量约1.4个周期,包括存储。它在前端吞吐量(每时钟3.75个融合域UOP)上大多是瓶颈,甚至在Clang的循环展开时也是如此,因为转换是5 UOP。
注意
有了一个负载和一个存储,这些存储就不能在haswell/skylake的port7存储agu上运行了,后者只处理非索引寻址模式。 对于英特尔CPU上的最大吞吐量(如果没有内存瓶颈),需要展开循环,因为加载+转换+存储已经是4个Uops。与@chtz的答案相同。
理想情况下,如果只需要读取浮点值几次,就可以立即使用向量结果进行进一步的计算。它只有3条指令(但对于无序的执行隐藏有一定的延迟)。在需要时重做转换可能比使用更大的缓存占用空间来存储两倍大的
|
![]() |
rookie · 检查函数模板的所有参数包参数是否属于int 1 年前 |
![]() |
ivaigult · -W转换和隐式字符串到布尔类型转换 1 年前 |
![]() |
rainer · 后台插入程序的初始化 1 年前 |
![]() |
Community wiki · 以理智、安全和高效的方式复制文件 1 年前 |
|
Shefali Kanaujia · 对C中向量的向量进行排序++ 1 年前 |
|
Ma Joonyoung · 粗粒度和细粒度链表的时间比较 1 年前 |