assembly - Arm64 中缺少 SSAT 和 USAT 指令的替代方案?
问题描述
我们正在将主要应用程序从 Arm32 移植到 Arm64。我们的算法经常使用SSAT
andUSAT
指令。它们非常有用,可以执行任意大小的左移或右移,然后执行有符号或无符号的饱和到任意位数。这对于图像处理算法非常有用,因为我们可以执行一些生成 32 位整数结果的数学运算,然后从中获取我们需要的任何位(饱和到输出图像的位深度的最大/最小值)一条指令。
这些指令在 Arm64 中莫名其妙地消失了,我们发现的最接近的替代方案是SQSHRN
/ UQSHRN
/ SQSHLN
/UQSHLN
它执行移位和饱和,但它们执行的饱和度受到更多限制(USAT
可以饱和到任何宽度,甚至 7 位;新指令可以仅饱和到输入宽度的一半,例如,在 32 位输入的情况下为 16 位,这将需要额外的处理才能获得所需的结果)。
有人可以解释为什么这些指令被删除,以及有效移植使用它们的现有代码的最佳方法是什么?
解决方案
--UPDATE-- 使用非汇编代码时,正确测试的时间明显变慢,我会继续寻找不同的方法
我比较了这个汇编代码:
#define __arm_ssat(src, bits) asm("ssat %[srcr], %[satv], %[srcr]" :[srcr]"+r"(src):[satv]"I"(bits));
有了这个:
#define MAX_SIGNED_NUM(bits) ((1 << (bits -1)) -1)
#define __arm_ssat(src, bits) {src = ((src > MAX_SIGNED_NUM(bits)) ? MAX_SIGNED_NUM(bits) : src);}
在 32 位设备上运行此 --UPDATED TEST-- 时:
volatile void assert_ssat_asm(int* buf, size_t loops){
int64_t num = buf[0];
int64_t num_a = buf[1];
int64_t num_b = buf[2];
int sum = 0;
struct timeval tmv1; gettimeofday(&tmv1,NULL);
for (int i = 0; i < loops; ++i){
__arm_ssat(num, 8);
sum+=num;
assert( 127 == num);
num = buf[0];
__arm_ssat(num, 16);
sum+=num;
assert(32767 == num);
__arm_ssat(num_a, 8);
sum+=num;
assert( 127 == num_a);
num_a = buf[1];
__arm_ssat(num_a, 16);
sum+=num;
assert( 690 == num_a);
__arm_ssat(num_b, 8);
sum+=num;
assert( 127 == num_b);
num_b = buf[2];
__arm_ssat(num_b, 16);
sum+=num;
assert( 32767 == num_b);
}
struct timeval tmv2; gettimeofday(&tmv2,NULL);
int tdiff_usec = (tmv2.tv_sec*1000000 + tmv2.tv_usec) - (tmv1.tv_sec*1000000 + tmv1.tv_usec);
printf("%d\n", sum);
printf("ran %d times, total time: %d, average time asm: %.7f\n", loops, tdiff_usec, (double)tdiff_usec/loops);
}
int main ()
{
int buf[] = { 69000, 690, 64000 };
test_ssat(buf, 1000000);
}
我得到了这些结果:
运行 1000000 次循环,平均时间 reg: 0.0210270
运行 1000000 次循环,平均组装时间:0.0057960
推荐阅读
- python - 使用 Telegram Bot 按下按钮时如何返回命令
- php - 将数组转换为查询php
- php - 找不到电报帐户类型
- python - python将现有变量获取到列表中
- python - 我正在尝试迭代一个函数的返回值,该函数返回一个由 3 个元组组成的元组
- crafter-cms - CrafterCMS:application.properties 位置
- c# - 拆分逗号分隔的字符串并存储到变量中
- spring - spring @controller vs @RestController 错误 whitelabel 错误
- vue.js - Vue.js - 通过 prop 对组件进行类绑定
- corda - 运行时出错 ./gradlew clean deployNodes