先看报错:
/home/orangepi/MNN-master/source/backend/cpu/arm/arm64/bf16/ARMV86_MNNPackedMatMulRemain_BF16.S:158: Fatal error: macros nested too deeply
再看代码:
PostTreatLH8:
FMAX v9, v15, v16, v17, v18
FMAX v9, v19, v20, v21, v22
FMAX v9, v23, v24, v25, v26
FMAX v9, v27, v28, v29, v30
FMIN v10, v15, v16, v17, v18
FMIN v10, v19, v20, v21, v22
FMIN v10, v23, v24, v25, v26
FMIN v10, v27, v28, v29, v30
这段代码中使用了多个 FMAX 和 FMIN 函数,它们分别计算一组向量 v15 到 v30 中的最大值和最小值,并将结果存储在两个不同的向量(v9 和 v10)中。具体来说,每个函数接受 5 个向量作为参数,例如:
(1)第一个 FMAX 函数 FMAX v9, v15, v16, v17, v18 计算向量 v15, v16, v17, v18 中的最大值,并将结果存储在 v9 向量中。
(2) 第二个 FMAX 函数 FMAX v9, v19, v20, v21, v22 计算向量 v19, v20, v21, v22 中的最大值,并将结果存储在 v9 向量中。
依此类推,第三个和第四个 FMAX 函数分别计算向量 v23 到 v26 和 v27 到 v30 中的最大值,并将结果存储在 v9 向量中。
类似地,第一个 FMIN 函数 FMIN v10, v15, v16, v17, v18 计算向量 v15, v16, v17, v18 中的最小值,并将结果存储在 v10 向量中。其余的 FMIN 函数依此类推,分别计算各自参数向量中的最小值,并将结果存储在 v10 向量中。
总之,这段代码的作用是计算给定向量组中的最大值和最小值,并将结果存储在两个新的向量中。这些计算通常用于图像处理和机器学习等领域中,以处理和提取特征向量等任务。
启动bf16进行构建时,源码的汇编指令嵌套过深,会导致编译时定义的宏无法展开,这个时候我们需要将指令集中所有关于FMAX和FMIN两个变量的嵌套调用展开,按照以下这种形式修改:
PostTreatLH8:
fmax v15.4s, v15.4s, v9.4s
fmax v16.4s, v16.4s, v9.4s
fmax v17.4s, v17.4s, v9.4s
fmax v18.4s, v18.4s, v9.4s
fmax v19.4s, v19.4s, v9.4s
fmax v20.4s, v20.4s, v9.4s
fmax v21.4s, v21.4s, v9.4s
fmax v22.4s, v22.4s, v9.4s
fmax v23.4s, v23.4s, v9.4s
fmax v24.4s, v24.4s, v9.4s
fmax v25.4s, v25.4s, v9.4s
fmax v26.4s, v26.4s, v9.4s
fmax v27.4s, v27.4s, v9.4s
fmax v28.4s, v28.4s, v9.4s
fmax v29.4s, v29.4s, v9.4s
fmax v30.4s, v30.4s, v9.4s
fmin v15.4s, v15.4s, v10.4s
fmin v16.4s, v16.4s, v10.4s
fmin v17.4s, v17.4s, v10.4s
fmin v18.4s, v18.4s, v10.4s
fmin v19.4s, v19.4s, v10.4s
fmin v20.4s, v20.4s, v10.4s
fmin v21.4s, v21.4s, v10.4s
fmin v22.4g, v22.4s, v10.4s
fmin v23.4s, v23.4s, v10.4s
fmin v24.4s, v24.4s, v10.4s
fmin v25.4s, v25.4s, v10.4s
fmin v26.4s, v26.4s, v10.4s
fmin v27.4s, v27.4s, v10.4s
fmin v28.4s, v28.4s, v10.4s
fmin v29.4s, v29.4s, v10.4s
fmin v30.4s, v30.4s, v10.4s
接下来看报错:
/home/orangepi/MNN-master/source/backend/cpu/arm/arm64/bf16/ARMV86_MNNPackedMatMul_BF16.S:174: Fatal error: macros nested too deeply
再看代码:
PostTreatLH8:
dup v5.4s, w17
dup v6.4s, w18
FMAX v5, v7, v8, v9, v10
FMAX v5, v11, v12, v13, v14
FMAX v5, v15, v16, v17, v18
FMAX v5, v19, v20, v21, v22
FMAX v5, v23, v24, v25, v26
FMAX v5, v27, v28, v29, v30
FMIN v6, v7, v8, v9, v10
FMIN v6, v11, v12, v13, v14
FMIN v6, v15, v16, v17, v18
FMIN v6, v19, v20, v21, v22
FMIN v6, v23, v24, v25, v26
按照以下这种形式修改:
PostTreatLH8:
dup v5.4s, w17
dup v6.4s, w18
fmax v7.4s, v7.4s, v5.4s
fmax v8.4s, v8.4s, v5.4s
fmax v9.4s, v9.4s, v5.4s
fmax v10.4s, v10.4s, v5.4s
fmax v11.4s, v11.4s, v5.4s
fmax v12.4s, v12.4s, v5.4s
fmax v13.4s, v13.4s, v5.4s
fmax v14.4s, v14.4s, v5.4s
fmax v15.4s, v15.4s, v5.4s
fmax v16.4s, v16.4s, v5.4s
fmax v17.4s, v17.4s, v5.4s
fmax v18.4s, v18.4s, v5.4s
fmax v19.4s, v19.4s, v5.4s
fmax v20.4s, v20.4s, v5.4s
fmax v21.4s, v21.4s, v5.4s
fmax v22.4s, v22.4s, v5.4s
fmax v23.4s, v23.4s, v5.4s
fmax v24.4s, v24.4s, v5.4s
fmax v25.4s, v25.4s, v5.4s
fmax v26.4s, v26.4s, v5.4s
fmax v27.4s, v27.4s, v5.4s
fmax v28.4s, v28.4s, v5.4s
fmax v29.4s, v29.4s, v5.4s
fmax v30.4s, v30.4s, v5.4s
fmin v7.4s, v7.4s, v6.4s
fmin v8.4s, v8.4s, v6.4s
fmin v9.4s, v9.4s, v6.4s
fmin v10.4s, v10.4s, v6.4s
fmin v11.4s, v11.4s, v6.4s
fmin v12.4s, v12.4s, v6.4s
fmin v13.4s, v13.4s, v6.4s
fmin v14.4s, v14.4s, v6.4s
fmin v15.4s, v15.4s, v6.4s
fmin v16.4s, v16.4s, v6.4s
fmin v17.4s, v17.4s, v6.4s
fmin v18.4s, v18.4s, v6.4s
fmin v19.4s, v19.4s, v6.4s
fmin v20.4s, v20.4s, v6.4s
fmin v21.4s, v21.4s, v6.4s
fmin v22.4s, v22.4s, v6.4s
fmin v23.4s, v23.4s, v6.4s
fmin v24.4s, v24.4s, v6.4s
fmin v25.4s, v25.4s, v6.4s
fmin v26.4s, v26.4s, v6.4s
这段代码使用了 ARM 架构中的向量寄存器(例如 v7.4s 和 v5.4s),它们可以同时存储多个浮点数或整数,并且通常用于图像处理和机器学习等领域。其中,FMAX 和 FMIN 函数分别用来计算一组向量中的最大值和最小值,并将结果存储在新的向量中。
具体来说,该代码首先使用 DUP 函数将标量 w17 和 w18 复制到向量 v5.4s 和 v6.4s 中。然后,它调用了 6 次 FMAX 函数和 5 次 FMIN 函数,每次传递 4 个向量参数。这意味着该代码实际上是将 24 个向量中的最大值和最小值分别存储在 v5.4s 和 v6.4s 中。
总之,该代码使用向量计算来高效地计算一组向量中的最大值和最小值,并且通过重复调用 FMAX 和 FMIN 函数来处理多个向量。这种方法可以在某些情况下比传统的循环方式更快,并且可以充分利用现代 CPU 的并行计算能力。