【发布时间】:2012-04-30 10:12:25
【问题描述】:
有一个很大的(~100 000)浮点点变量数组,并且有一个阈值(也是浮点点)。
问题是我必须将数组中的每个变量与阈值进行比较,但 NEON 标志传输需要很长时间(根据分析器,大约 20 个周期)。
有什么有效的方法来比较这些值吗?
注意:由于舍入误差无关紧要,我尝试了以下方法:
float arr[10000];
float threshold;
....
int a = arr[20]; // e.g.
int t = threshold;
if (t > a) {....}
但在这种情况下,我得到以下处理器命令序列:
vldr.32 s0, [r0]
vcvt.s32.f32 s0, s0
vmov r0, s0 <--- takes 20 cycles as `vmrs APSR_nzcv, fpscr` in case of
cmp r0, r1 floating point comparison
由于在 NEON 上发生转换,所以无论我是通过描述的方式还是浮点数来比较整数。
【问题讨论】:
-
您的代码与您的问题陈述不一致 - 数据是浮点数,但您将阈值显示为 int - 您还将每个浮点数据值转换为 int - 为什么?如果您的数据是浮动的,那么阈值应该是浮动的,您应该进行浮动比较(即没有 int-float 转换)。另外,您打算如何处理大于(或小于)阈值的值(这将确定 NEON 是否合适)?
-
许多人放弃了 NEON,因为它比 ARM 慢,却不知道要避免什么以及如何正确编程 SIMD。根据您的确切需求,从 SIMD 开始可能不可行,或者您不知道如何使用 NEON 处理 if-else。
-
if-else on NEON : 1. 使用 VCnn 指令创建掩码值。 2. 在两个不同的寄存器中计算两种情况(如果、否则)的结果。 3. 使用 1 中的掩码值将两个结果与 VBnn 指令结合。
-
由于无论是否满足条件,您总是必须在 NEON 上计算这两种情况,如果计算非常复杂,它可能比在 ARM 上慢。如果有多个关联的 if-else,忘记 NEON。
-
NEON->ARM 寄存器传输总是需要 11~14 个周期。应该不惜一切代价在循环内避免这种情况。为什么即使没有舍入误差也可以非常快速地比较浮点数时使用这些类型转换?我将在单独的答案中向您展示。