gcc中的速度关键部分?

问题描述 投票:1回答:1

我已经在使用-O3,所以我一般认为我不能做得更好,但是生成的程序集仍然非常适合时序要求。例如,是否有一种方法可以告诉avr-gcc将非速度关键的代码排除在速度关键的部分之外?

if (READY)
{
    ACKNOWLEDGE();

    SETUP_PART1();
    SETUP_PART2();

    //start speed-critical section
    SYNC_TO_TIMER();
    MINIMAL_SPEED_CRITICAL_CODE();
    //end speed-critical section

    CLEANUP();
}

-O3优化的程序集清单(.lss文件)的单调乏味的阅读显示,SETUP_PART2();已重新排序为介于SYNC_TO_TIMER();MINIMAL_SPEED_CRITICAL_CODE();之间。这是一个问题,因为它增加了在速度关键部分不需要的时间。

我不想将关键部分本身制作得比需要的时间长,因此我不愿意放松优化。 (导致此问题的相同动作也可能是使最终版本在可用时间内适合您的原因)那么我怎么能告诉它“此行为”需要保持简洁,整洁,但仍要对其进行充分优化?


我以前使用过内联汇编,所以我确定我可以再次弄清楚如何在C和C之间进行通信,而不必完全占用或破坏寄存器等。但是如果我愿意,我宁愿坚持使用100%C可以,让编译器弄清楚如何不对其自身运行。

compiler-optimization avr-gcc
1个回答
0
投票

不是我要找的直接答案,但是我发现了一些可行的方法。因此,从技术上讲,这是一个XY问题,但我仍将直接回答上述问题。


这是我最终要做的:

1.将速度关键部分分成自己的功能,并防止其内联:

void __attribute__((noinline)) _fast_function(uint8_t arg1, uint8_t arg2)
{
    //start speed-critical section
    SYNC_TO_TIMER();
    MINIMAL_SPEED_CRITICAL_CODE(arg1, arg2);
    //end speed-critical section
}

void normal_function(void)
{
    if (READY)
    {
        ACKNOWLEDGE();

        SETUP_PART1();
        SETUP_PART2();  //determines arg1, arg2

        _fast_function(arg1, arg2);

        CLEANUP();
    }
}

这将对速度要求苛刻的东西放在一起,而且靠自己。它也增加了一些开销,但是这超出了我可以负担得起的快速部分。

2.手动展开一些循环:

原始代码是这样的:

uint8_t data[3];

uint8_t byte_num = 3;
while(byte_num)
{
    byte_num--;

    uint8_t bit_mask = 0b10000000;
    while(bit_mask)
    {
        if(data[byte_num] & bit_mask)   WEIRD_OUTPUT_1();
        else                            WEIRD_OUTPUT_0();

        bit_mask >>= 1;
    }
}

新代码如下:

#define WEIRD_OUTPUT(byte,bit)                  \
    do                                          \
    {                                           \
        if((byte) & (bit))  WEIRD_OUTPUT_1();   \
        else                WEIRD_OUTPUT_0();   \
    } while(0)

uint8_t data[3];

WEIRD_OUTPUT(data[2],0b10000000);
WEIRD_OUTPUT(data[2],0b01000000);
WEIRD_OUTPUT(data[2],0b00100000);
WEIRD_OUTPUT(data[2],0b00010000);
WEIRD_OUTPUT(data[2],0b00001000);
WEIRD_OUTPUT(data[2],0b00000100);
WEIRD_OUTPUT(data[2],0b00000010);
WEIRD_OUTPUT(data[2],0b00000001);

WEIRD_OUTPUT(data[1],0b10000000);
WEIRD_OUTPUT(data[1],0b01000000);
WEIRD_OUTPUT(data[1],0b00100000);
WEIRD_OUTPUT(data[1],0b00010000);
WEIRD_OUTPUT(data[1],0b00001000);
WEIRD_OUTPUT(data[1],0b00000100);
WEIRD_OUTPUT(data[1],0b00000010);
WEIRD_OUTPUT(data[1],0b00000001);

WEIRD_OUTPUT(data[0],0b10000000);
WEIRD_OUTPUT(data[0],0b01000000);
WEIRD_OUTPUT(data[0],0b00100000);
WEIRD_OUTPUT(data[0],0b00010000);
WEIRD_OUTPUT(data[0],0b00001000);
WEIRD_OUTPUT(data[0],0b00000100);
WEIRD_OUTPUT(data[0],0b00000010);
WEIRD_OUTPUT(data[0],0b00000001);

除了删除循环代码本身之外,这还用直接访问替换了数组索引,并用常量替换了变量,每个常量都提供自己的加速。

而且它仍然无法适应现有时间。 但是确实合适!:)

© www.soinside.com 2019 - 2024. All rights reserved.