ARM Neon 内在函数 - FMA 中的通道

问题描述 投票:0回答:1

我是 ARM NEON 内在函数的新手,正在查看它的文档。他们提供了一组很棒的示例,其中包括一个使用向量 FMA 指令的矩阵乘法示例。然而我对最后一个参数感到相当困惑。这是代码摘录。

    C0 = vfmaq_laneq_f32(C0, A0, B0, 0);
    C0 = vfmaq_laneq_f32(C0, A1, B0, 1);
    C0 = vfmaq_laneq_f32(C0, A2, B0, 2);
    C0 = vfmaq_laneq_f32(C0, A3, B0, 3);

最后的0,1,2,3是让我困惑的部分。从这里找到的文档: https://developer.arm.com/architectures/instruction-sets/intrinsics/#q=vfmaq_laneq_f32 这是指通道。从我读过的其他文档中,通道指的是打包变量是否分为 64、32、16 或 8 位大小的数据类型,这在这种情况下没有意义。我可能遗漏了一些东西,但对我来说,他们似乎在这里使用相同的词,但含义不同。

那么车道在这种情况下意味着什么?如果我反转订单会发生什么?如果我将它们全部设置为 0 会发生什么?

注意:这是矩阵乘法示例的链接 https://developer.arm.com/documentation/102467/0201/示例---矩阵乘法

c++ arm arm64 intrinsics neon
1个回答
0
投票

奇怪,对应的asm指令(https://developer.arm.com/documentation/ddi0596/2021-03/SIMD-FP-Instructions/FMLA--vector---Floating-point-fused-Multiply-Add- to-accumulator--vector--?lang=en 从您链接的内在文档中的 FMLA 超链接链接)没有提到输入向量之一的索引。

但是 FMLA(按元素) 确实如此:它广播第二个乘数向量的一个元素,而不是纯垂直的。

其操作伪代码为:

CheckFPAdvSIMDEnabled64();
bits(datasize) operand1 = V[n];
bits(idxdsize) operand2 = V[m];
bits(datasize) operand3 = V[d];
bits(esize) element1;
bits(esize) element2 = Elem[operand2, index, esize];
FPCRType fpcr = FPCR[];
boolean merge    = elements == 1 && IsMerging(fpcr);
bits(128) result = if merge then V[d] else Zeros();

for e = 0 to elements-1
    element1 = Elem[operand1, e, esize];
    if sub_op then element1 = FPNeg(element1);
    Elem[result, e, esize] = FPMulAdd(Elem[operand3, e, esize], element1, element2, fpcr);

V[d] = result;

请注意,

element2
在循环外部进行索引,并用于循环内部的 4 个元素中的每一个。 (或双精度 128 位向量为 2 个元素,或单精度 64 位向量为 2 个元素,或 128 位半精度为 8 个元素)。

我认为内在函数使用与 asm 不同的操作数顺序:在 asm 中,累加器是第一个操作数,因此它也可以是目标。但我认为内在函数符合通常的 ISO C

fma(mul1, mul2, add)
操作数顺序。

因此,这是使用

B0
的每个元素作为不同 A 向量的乘数,而不是对该行的每个元素进行单独的广播加载。这是 matmul 想要做的事情。


因此,内在文档令人困惑,因为它们链接(并从中复制伪代码)纯垂直 FMLA 指令,而不是通道广播版本。

© www.soinside.com 2019 - 2024. All rights reserved.