我已经养成了在我的代码中尽可能使用无符号整数的习惯,因为处理器可以在无符号类型上除以2的幂,而不能使用有符号类型。速度对这个项目至关重要。处理器的运行速度高达40 MIPS。
我的处理器有18个周期的分频,但它需要比单周期桶形移位器更长的时间。那么值得在这里使用无符号整数来加快速度还是带来其他缺点?我使用的是dsPIC33FJ128GP802-- Microchip的dsPIC33F系列的成员。对于有符号和无符号整数,它具有单周期乘法。它还有符号和零扩展指令。
例如,它在混合有符号和无符号整数时生成此代码。
026E4 97E80F mov.b [w15-24],w0
026E6 FB0000 se w0,w0
026E8 97E11F mov.b [w15-31],w2
026EA FB8102 ze w2,w2
026EC B98002 mul.ss w0,w2,w0
026EE 400600 add.w w0,w0,w12
026F0 FB8003 ze w3,w0
026F2 100770 subr.w w0,#16,w14
我正在使用C(用于dsPIC的GCC。)
答案 0 :(得分:2)
我认为我们都需要了解更多关于处理器回答这个问题的特性。为什么它不能在有符号整数上除以2的幂?据我记得,两者的操作是相同的。即。
10/2 = 00001010转到00000101
-10/2 = 11110110转到11111011
也许你应该写一些简单的代码做无符号除法和有符号除法并比较编译后的输出。
基准测试也是一个好主意。它不需要精确。只需要一个包含几千个数字的数组,启动计时器并开始将它们分成几百万次并计算所需的时间。如果您的处理器速度很快,也许可以做几十亿次。 E.g。
int s_numbers[] = { etc. etc. };
int s_array_size = sizeof(s_numbers);
unsigned int u_numbers[] = { etc. etc.};
unsigned int u_array_size = sizeof(u_numbers);
int i;
int s_result;
unsigned int u_result;
/* Start timer. */
for(i = 0; i < 100000000; i++)
{
i_result = s_numbers[i % s_array_size] / s_numbers[(i + 1) % s_array_size];
}
/* Stop timer and print difference. */
/* Repeat for unsigned integers. */
急着写出原则,请原谅任何错误。
它不会给出精确的基准测试,但应该大致了解哪个更快。
答案 1 :(得分:0)
我对处理器上可用的指令集了解不多,但快速查看让我觉得它有可用于算术和逻辑转换的指令,这应该意味着转移有符号值的成本大约是与移位无符号值相同,并且每次使用移位除以2的幂也应该相同。 (我对此的了解是快速浏览一下针对处理器系列的C编译器的一些内部函数。)
话虽如此,如果您正在使用要解释为unsigned的值,那么您也可以将它们声明为unsigned。在过去的几年里,我一直在使用stdint.h中的类型越来越多,而且我最终使用的是无符号版本,因为我的值本身就是无符号的,或者我只是将它们用作位数组。
答案 2 :(得分:0)
生成两种方式的装配和计算周期。
答案 3 :(得分:0)
我猜测两位的无符号除法速度更快,因为它可以根据需要简单地进行右移,而无需担心符号扩展。
至于缺点:检测算术溢出,溢出签名类型,因为你在使用无符号时没有意识到,等等。没有任何阻塞,只需要注意不同的事情。