VNNI 指令的 NEON 仿真

Posted

技术标签:

【中文标题】VNNI 指令的 NEON 仿真【英文标题】:NEON emulation of VNNI instructions 【发布时间】:2020-03-10 12:26:55 【问题描述】:

Cascade Lake Intel CPU 中有新的AVX-512 VNNI 指令,可以加速 CPU 上的神经网络推理。 我将它们集成到Simd Library 以加速Synet(我的神经网络推理小框架)并获得显着的性能提升。

事实上,我只使用了一条指令_mm512_dpbusd_epi32 (vpdpbusd),它允许执行 8 位有符号和无符号整数的乘法,然后将它们累加到 32 位整数累加器中。

为 NEON(ARM 平台)执行模拟优化会很棒。

所以有一个问题:

是否存在任何类似 NEON 指令的模拟 vpdpbusd?如果没有类似物,模拟指令的最佳方法是什么?

下面有一个标量实现(为了更好地理解函数必须做什么):

inline void pdpbusd(int32x4_t& sum, uint8x16_t input, int8x16_t weight)

    for (size_t i = 0; i < 4; ++i)
        for (size_t j = 0; j < 4; ++j)
            sum[i] += int32_t(input[i * 4 + j]) * int32_t(weight[i * 4 + j]);

【问题讨论】:

Ermig,请披露您与 synet 项目的隶属关系。另外,请改写项目描述,“推理”不是动词,我觉得你正在使用它作为一个动词。松散相关的推荐阅读:***.com/help/promotion 【参考方案1】:

最直接的实现需要 3 条指令; vmovl.s8, vmovl.u8 将有符号和无符号 8 位值扩展为 16 位,然后 vmlal.s16 进行有符号延长 16 位乘法,累加到 32 位寄存器中。由于 vmlal.s16 仅处理 4 个元素,您需要第二个 vmlal.s16 来相乘和累加以下 4 个元素 - 所以 4 个元素的 4 条指令。

对于aarch64语法,对应的指令为sxtluxtlsmlal

编辑: 如果输出元素应该水平聚合,则不能使用融合乘法累加指令vmlal。那么解决方案将是vmovl.s8vmovl.u8,然后是vmul.i16(用于8 个输入元素),vpaddl.s16(水平聚合两个元素),然后是另一个vpadd.i32,以获得水平方向4 个元素的总和.所以 5 条指令对应 8 个输入元素,或者 10 条指令对应完整的 128 位向量,然后是最后一条 vadd.s32 将最终结果累加到累加器中。在 AArch64 上,相当于vpadd.i32addp,可以处理 128 位向量,因此少了一条指令。

如果您使用的是 instrinsics,则实现可能如下所示:

int32x4_t vpdpbusd(int32x4_t sum, uint8x16_t input, int8x16_t weight) 
    int16x8_t i1 = vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(input)));
    int16x8_t i2 = vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(input)));
    int16x8_t w1 = vmovl_s8(vget_low_s8(weight));
    int16x8_t w2 = vmovl_s8(vget_high_s8(weight));
    int16x8_t p1 = vmulq_s16(i1, w1);
    int16x8_t p2 = vmulq_s16(i2, w2);
    int32x4_t s1 = vpaddlq_s16(p1);
    int32x4_t s2 = vpaddlq_s16(p2);
#if defined(__aarch64__)
    int32x4_t s3 = vpaddq_s32(s1, s2);
#else
    int32x4_t s3 = vcombine_s32(
        vpadd_s32(vget_low_s32(s1), vget_high_s32(s1)),
        vpadd_s32(vget_low_s32(s2), vget_high_s32(s2))
    );  
#endif
    sum = vaddq_s32(sum, s3);
    return sum;

【讨论】:

所以我们可以用 6 条指令来模拟它? 不,4 条指令。对于从 8 位有符号和无符号输入中的每一个处理的 8 个输入元素,您需要 1 个vmovl.s8、1 个vmovl.u8 和 2 个vmlal.s16 来处理它们。 或 8 条指令用于 128 位向量。 很遗憾,您的解决方案无法正常工作(请参阅上面的标量实现)。 对,所以如果你想同时聚合单独的 4 个相邻元素,它需要更多的代码,因为不能使用融合乘法累加指令,我将编辑相应地回答。

以上是关于VNNI 指令的 NEON 仿真的主要内容,如果未能解决你的问题,请参考以下文章

Modelsim 仿真指令force用法

是否可以在 Intel SDE 中结合 CPUID 和指令集仿真参数

ACR122u卡仿真模式发送PN532指令

PX4APM无人机仿真连接QGC地面站记录

PX4APM无人机仿真连接QGC地面站记录

PX4APM无人机仿真连接QGC地面站记录(udp连接更改home点等)