我尝试减少此功能的执行时间,并将执行时间缩短为
SYS:0.001S
有没有办法进一步减少这个功能的执行时间?
int function(uint32_t *r, const uint32_t *a, const uint32_t *b, int n)
{
int i;
uint32_t ri, c=0;
for (i = 0; i < n; i ++)
{
ri = a[i] + b[i] + c;
c = ((ri < a[i]) || ((ri == a[i]) && c));
r[i] = ri;
}
return ((int) c);
}
答案 0 :(得分:1)
我想,你在条件表达式中大部分时间都处于松散状态:如果大多数时候他们无法正确预测,大多数现代CPU讨厌分支。因此,大多数循环引入的分支都很好,因为它们只对整个循环进行了一次错误预测。然而,在携带条件下进行分支可能会导致50%的分支被错误预测,并且每次错误预测都值10到20个周期。更糟糕的是,&&
和||
运算符是序列点,这是优化器的障碍。
所以,我会尝试消除这些条件:
int function(uint32_t *r, const uint32_t *a, const uint32_t *b, int n) {
int i;
uint64_t ri, c=0;
for (i = 0; i < n; i ++) {
ri = (uint64_t)a[i] + (uint64_t)b[i] + c;
c = ri >> 32;
r[i] = (uint32_t)ri;
}
return ((int) c);
}
这里,我使用了64位运算,因为现代CPU的运算速度与32位运算一样快。但是,如果硬件上的64位算术速度很慢,则可以回退到32位算术:
int function(uint32_t *r, const uint32_t *a, const uint32_t *b, int n) {
int i;
uint32_t ri, c=0;
for (i = 0; i < n; i ++) {
uint32_t curA = a[i], curB = b[i];
uint32_t lowA = curA & 0xffffu, highA = curA >> 16;
uint32_t lowB = curB & 0xffffu, highB = curB >> 16;
uint32_t lowR = lowA + lowB + c;
uint32_t highR = highA + highB + (lowR >> 16);
c = highR >> 16;
r[i] = (highR << 16) + lowR;
}
return ((int) c);
}
即使这看起来像一个怪物,它只有12个简单的操作,应该在所有硬件上以一个周期的延迟执行,i。即整个循环体的计算应该少于12个循环,因此,瓶颈应该是内存总线(你无法避免)。
答案 1 :(得分:0)
你可以摆脱下标符号并使用指针运算代替据说更快,但我不知道实际节省多少CPU时间。
int function(uint32_t *r, const uint32_t *a, const uint32_t *b, int n)
{
int i;
uint32_t ri, c=0;
for (i = 0; i < n; i ++)
{
ri = *(a + i) + *(b + i) + c;
c = ((ri < *(a + i)) || ((ri == *(a +i)) && c));
*(r + i) = ri;
}
return ((int) c);
}
原因见:Accessing array values via pointer arithmetic vs. subscripting in C
答案 2 :(得分:0)
c =(ri&lt; a [i])+((ri-a [i])* c)可能比你的代码更快,如果c == 0
也会测试