реклама на сайте
подробности

 
 
> Оптимизация алгоритма на С, вопрос к знатокам компиляторов
singlskv
сообщение Aug 23 2006, 21:50
Сообщение #1


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Есть два варианта функции вычисления CRC:
Код
unsigned char code[8]={0x01,0xd0,0x5e,0x3c,0x0d,0x00,0x00,0x84};

unsigned char crc8_1(unsigned char *buff,unsigned char num)
{
    unsigned char i=0,j,tmp,data,crc=0;
    for (i=0;i<num;i++) {
        data=*buff++;
        for (j=0;j<8;j++) {
            tmp=1&(data^crc);
            crc>>=1;
            data>>=1;
            if (tmp!=0) crc^=0x8c;
        }
    }
    return crc;
}

unsigned char crc8_2(unsigned char *buff,unsigned char num)
{
    unsigned char i=num,j,tmp,data,crc=0;
    for (;i>0;i--) {
        data=*buff++;
        for (j=8;j>0;j--) {
            tmp=1&(data^crc);
            crc>>=1;
            data>>=1;
            if (tmp!=0) crc^=0x8c;
        }
    }
    return crc;
}

int main(int argc, char* argv[])
{
    unsigned char crc_;
    crc_=crc8_1(code,7);
    crc_=crc8_2(code,7);
    return 0;
}


Как видно из рисунка, это собственно один и тот же алгоритм.
Но, при компиляции под WinAVR(gcc), при любом уровне оптимизации, второй
вариант работает на 10-15% быстрее.
Собственно вопрос: а есть ли компилятор который может скомпилировать
эти две(одинаковых!) функции в одинаковый(быстрый) код ?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
vet
сообщение Aug 24 2006, 10:20
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32



Скомпилировал в IAR 4.11A два цикла for с инкрементом от 0 до 8 и декрементом от 8 до 0, макс.оптимизация по скорости. Код одинаков.
Код
        RSEG CODE:CODE:NOROOT(1)
//    3 void main() {
main:
//    4 char i;

//    5   for (i=0;i<8;i++) {
        LDI    R16, 8
//    6     asm("nop");
??main_0:
        nop
//    7   }
        DEC    R16
        BRNE    ??main_0

//    8   for (i=8;i;i--) {
        LDI    R16, 8
//    9     asm("nop");
??main_1:
        nop
//   10   }
        DEC    R16
        BRNE    ??main_1

//   11 }
        RET



Выкладываю листинг компиляции вышеприведённого исходника:
Код
        RSEG CODE:CODE:NOROOT(1)
//    3 unsigned char crc8_1(unsigned char *buff,unsigned char num)
crc8_1:
//    4 {
//    5     unsigned char i=0,j,tmp,data,crc=0;
        LDI    R21, 0
//    6     for (i=0;i<num;i++) {
        LDI    R20, 0
        RJMP    ??crc8_1_0
//    7         data=*buff++;
??crc8_1_1:
        MOVW    R31:R30, R17:R16
        LD    R23, Z+
        MOVW    R17:R16, R31:R30
//    8         for (j=0;j<8;j++) {
        LDI    R19, 8
//    9             tmp=1&(data^crc);
??crc8_1_2:
        MOV    R0, R23
        BST    R0, 0
        CLR    R0
        BLD    R0, 0
        MOV    R22, R21
        ANDI    R22, 0x01
        EOR    R22, R0
        ANDI    R22, 0x01
//   10             crc>>=1;
        LSR    R21
//   11             data>>=1;
        LSR    R23
//   12             if (tmp!=0) crc^=0x8c;
        TST    R22
        BREQ    ??crc8_1_3
        LDI    R22, 140
        EOR    R21, R22
//   13         }
??crc8_1_3:
        DEC    R19
        BRNE    ??crc8_1_2
//   14     }
        INC    R20
??crc8_1_0:
        CP    R20, R18
        BRCS    ??crc8_1_1
//   15     return crc;
        MOV    R16, R21
        RET
//   16 }
//   17

        RSEG CODE:CODE:NOROOT(1)
//   18 unsigned char crc8_2(unsigned char *buff,unsigned char num)
crc8_2:
//   19 {
//   20     unsigned char i=num,j,tmp,data,crc=0;
        MOV    R19, R18
        LDI    R20, 0
        RJMP    ??crc8_2_0
//   21     for (;i>0;i--) {
//   22         data=*buff++;
??crc8_2_1:
        MOVW    R31:R30, R17:R16
        LD    R22, Z+
        MOVW    R17:R16, R31:R30
//   23         for (j=8;j>0;j--) {
        LDI    R18, 8
//   24             tmp=1&(data^crc);
??crc8_2_2:
        MOV    R23, R22
        ANDI    R23, 0x01
        MOV    R21, R20
        ANDI    R21, 0x01
        EOR    R21, R23
        ANDI    R21, 0x01
//   25             crc>>=1;
        LSR    R20
//   26             data>>=1;
        LSR    R22
//   27             if (tmp!=0) crc^=0x8c;
        TST    R21
        BREQ    ??crc8_2_3
        LDI    R21, 140
        EOR    R20, R21
//   28         }
??crc8_2_3:
        DEC    R18
        BRNE    ??crc8_2_2
//   29     }
        DEC    R19
??crc8_2_0:
        TST    R19
        BRNE    ??crc8_2_1
//   30     return crc;
        MOV    R16, R20
        RET
//   31 }
//   32

Во второй функции компилятор решил задачу по-другому, но накладные расходы на цикл одинаковы в обеих функциях.

Сообщение отредактировал vet - Aug 24 2006, 10:37


--------------------
Главная линия этого опуса ясна мне насквозь!
Go to the top of the page
 
+Quote Post
Old1
сообщение Aug 24 2006, 17:12
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 697
Регистрация: 26-07-05
Из: Могилев
Пользователь №: 7 095



Цитата(vet @ Aug 24 2006, 13:20) *
Скомпилировал в IAR 4.11A два цикла for с инкрементом от 0 до 8 и декрементом от 8 до 0, макс.оптимизация по скорости. Код одинаков.
...

Но если поставить оптимизацию по объему кода, то появляется тот эффект о котором писал автор, функция с циклом с декрементом выполняется быстрее. (Я обычно использую оптимизацию по объему, и когда спрашивал упустил, что автора интересует максимальная скорость.)
Go to the top of the page
 
+Quote Post
µµC
сообщение Aug 24 2006, 19:24
Сообщение #4


Участник
*

Группа: Новичок
Сообщений: 44
Регистрация: 2-05-06
Пользователь №: 16 710



Цитата(Old1 @ Aug 24 2006, 21:12) *
Но если поставить оптимизацию по объему кода, то появляется тот эффект о котором писал автор, функция с циклом с декрементом выполняется быстрее.


Человек явно ищет идеальный компилятор, а их, как известно, в природе не бывает. От программиста требуется хорошо знать какой будет код в какой ситуации, "чувствовать селезенкой", "заставлять" компилятор быть эффективным. Например:

Код
U8 CRC8_1 (U8 val, U8 crc)
{
  U8 tmp;
  U8 i = 8;
  do {
    tmp = (val ^ crc) & 0x01;
    crc >>= 1;
    val >>= 1;
    if (tmp != 0) crc ^= 0x8c;
  } while (--i);
  return crc;
}

U8 CRC8_1 (U8 val, U8 crc)
{
  U8 tmp;
  U8 i = 8;
  do {
    tmp = (val ^ crc);
    crc >>= 1;
    val >>= 1;
    if (tmp & 0x01) crc ^= 0x8c;
  } while (--i);
  return crc;
}


154 цикла к 122. А, казалось бы, от перемены мест ...
Go to the top of the page
 
+Quote Post
singlskv
сообщение Aug 24 2006, 20:29
Сообщение #5


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(µµC @ Aug 24 2006, 23:24) *
Человек явно ищет идеальный компилятор, а их, как известно, в природе не бывает.

Лучший компилятор это человек.
на ASM у меня получилось 530 тактов:
Код
crc8:    ;Input: X - buffer; r17 - number of bytes    
    ;Output: r16 = CRC

    ldi    r16,0    ;CRC
    ldi    r20,0x8c
crc8_1:
    ld    r18,X+
    ldi    r19,8
crc8_2:
    lsr    r16
    brbc    0,crc8_3
    eor    r16,r20
crc8_3:
    sbrc    r18,0
    eor    r16,r20
    lsr    r18
crc8_4:
    dec    r19
    brne    crc8_2
    dec    r17
    brne    crc8_1

    ret


НО, надо отдать должное WinAVR(gcc)

ИТОГО:
Код
                    CRC8_1    CRC8_2
WinAVR(-o1)        620           556
WinAVR(-o2)        620           556
WinAVR(-o3)        606           544

IAR                986           774

ASM                       530


У WinAVR(-o3) удалось украсть всего 14 тактов, то есть по 2 такта на основной цикл.
Приятно удививший результат cheers.gif

А с IAR просто какая-то лабудень, возможно Вы vet там чего-то не то указали при
оптимизации?
Go to the top of the page
 
+Quote Post
_Bill
сообщение Aug 25 2006, 11:17
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(singlskv @ Aug 24 2006, 23:29) *
Цитата(µµC @ Aug 24 2006, 23:24) *

Человек явно ищет идеальный компилятор, а их, как известно, в природе не бывает.

Лучший компилятор это человек.
на ASM у меня получилось 530 тактов:
Код
crc8:;Input: X - buffer; r17 - number of bytes    
;Output: r16 = CRC

    ldi    r16,0;CRC
    ldi    r20,0x8c
crc8_1:
    ld    r18,X+
    ldi    r19,8
crc8_2:
    lsr    r16
    brbc    0,crc8_3
    eor    r16,r20
crc8_3:
    sbrc    r18,0
    eor    r16,r20
    lsr    r18
crc8_4:
    dec    r19
    brne    crc8_2
    dec    r17
    brne    crc8_1

    ret


НО, надо отдать должное WinAVR(gcc)

ИТОГО:
Код
                    CRC8_1    CRC8_2
WinAVR(-o1)        620           556
WinAVR(-o2)        620           556
WinAVR(-o3)        606           544

IAR                986           774

ASM                       530


У WinAVR(-o3) удалось украсть всего 14 тактов, то есть по 2 такта на основной цикл.
Приятно удививший результат cheers.gif

А с IAR просто какая-то лабудень, возможно Вы vet там чего-то не то указали при
оптимизации?

Вся проблема в том, что компилятор использует определенные соглашения по передаче параметров и использованию регистров. Ваша функция под соглашения, принятые, например, в IAR, не попадает. Для стыковки с Си-шными функциями ее потребуется изменить с принятыми в компиляторе соглашениями. А это приведет к увеличению и размера кода, и увеличением времени его выполнения.

Сообщение отредактировал _Bill - Aug 25 2006, 11:33
Go to the top of the page
 
+Quote Post
singlskv
сообщение Aug 25 2006, 11:26
Сообщение #7


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(_Bill @ Aug 25 2006, 15:17) *
Цитата(singlskv @ Aug 24 2006, 23:29) *

Цитата(µµC @ Aug 24 2006, 23:24) *

Человек явно ищет идеальный компилятор, а их, как известно, в природе не бывает.

Лучший компилятор это человек.
на ASM у меня получилось 530 тактов:
Код
crc8:;Input: X - buffer; r17 - number of bytes    
;Output: r16 = CRC

    ldi    r16,0;CRC
    ldi    r20,0x8c
crc8_1:
    ld    r18,X+
    ldi    r19,8
crc8_2:
    lsr    r16
    brbc    0,crc8_3
    eor    r16,r20
crc8_3:
    sbrc    r18,0
    eor    r16,r20
    lsr    r18
crc8_4:
    dec    r19
    brne    crc8_2
    dec    r17
    brne    crc8_1

    ret


НО, надо отдать должное WinAVR(gcc)

ИТОГО:
Код
                    CRC8_1    CRC8_2
WinAVR(-o1)        620           556
WinAVR(-o2)        620           556
WinAVR(-o3)        606           544

IAR                986           774

ASM                       530


У WinAVR(-o3) удалось украсть всего 14 тактов, то есть по 2 такта на основной цикл.
Приятно удививший результат cheers.gif

А с IAR просто какая-то лабудень, возможно Вы vet там чего-то не то указали при
оптимизации?

Вся проблема в том, что компилятор использует определенные соглашения по передаче параметров и использованию регистров. Ваша функция под соглашения, принятые, например, в IAR, не попадает. Для стыковки с Си-шными функциями ее потребуется изменить с принятыми в компиляторе соглашениями. А это приведет к увеличению и размера кода, и увеличением времени его выполнения.


Цитата(singlskv @ Aug 24 2006, 23:29) *
Цитата(µµC @ Aug 24 2006, 23:24) *

Человек явно ищет идеальный компилятор, а их, как известно, в природе не бывает.

Лучший компилятор это человек.
на ASM у меня получилось 530 тактов:
Код
crc8:;Input: X - buffer; r17 - number of bytes    
;Output: r16 = CRC

    ldi    r16,0;CRC
    ldi    r20,0x8c
crc8_1:
    ld    r18,X+
    ldi    r19,8
crc8_2:
    lsr    r16
    brbc    0,crc8_3
    eor    r16,r20
crc8_3:
    sbrc    r18,0
    eor    r16,r20
    lsr    r18
crc8_4:
    dec    r19
    brne    crc8_2
    dec    r17
    brne    crc8_1

    ret


НО, надо отдать должное WinAVR(gcc)

ИТОГО:
Код
                    CRC8_1    CRC8_2
WinAVR(-o1)        620           556
WinAVR(-o2)        620           556
WinAVR(-o3)        606           544

IAR                986           774

ASM                       530


У WinAVR(-o3) удалось украсть всего 14 тактов, то есть по 2 такта на основной цикл.
Приятно удививший результат cheers.gif

А с IAR просто какая-то лабудень, возможно Вы vet там чего-то не то указали при
оптимизации?

Вся проблема в том, что компилятор использует определенные соглашения по передаче параметров и использованию регистров. Ваша функция под соглашения, принятые, например, в IAR, не попадает. Для стыковки с Си-шными функциями ее потребуется изменить с принятыми в компиляторе соглашениями. А это приведет к увеличению и размера кода, и увеличением времени его выполнения.

такты я считал по возможности честно, т.е. не учитывая такты потраченные на передачу
параметров.
А мой ASM код можно легко переписать под нужные регистры. smile.gif
Да и разница в тактах что-то великовата, что бы ее объяснять только передачей
параметров.

Сообщение отредактировал singlskv - Aug 25 2006, 11:39
Go to the top of the page
 
+Quote Post
_Bill
сообщение Aug 25 2006, 11:47
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(singlskv @ Aug 25 2006, 14:26) *
такты я считал по возможности честно, т.е. не учитывая такты потраченные на передачу
параметров.
А мой ASM код можно легко переписать под нужные регистры. smile.gif

Не сомневаюсь, но код все равно получится длиннее. И, опять же, если Вы используете свои собственные соглашения по передаче параметров и использованию регистров в ваших модулях на ассемблере, то Вы будете вынуждены писать Ваши функции в соответствии с принятыми Вами соглашениями. А это неизбежно приведет к увеличению кода аналогично тому, как это делается компилятором.
В свое время я написал небольшой опус на эту тему. К сожалению, он и сейчас далек от завершения.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Aug 25 2006, 12:30
Сообщение #9


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(_Bill @ Aug 25 2006, 15:47) *
Цитата(singlskv @ Aug 25 2006, 14:26) *

такты я считал по возможности честно, т.е. не учитывая такты потраченные на передачу
параметров.
А мой ASM код можно легко переписать под нужные регистры. smile.gif

В свое время я написал небольшой опус на эту тему. К сожалению, он и сейчас далек от завершения.


Несколько месяцев назад прочитал Ваш опус, очень понравилось a14.gif
Так что Вас можно считать идейным вдохновителем данного топика smile.gif
Цитата(_Bill @ Aug 25 2006, 15:47) *
Не сомневаюсь, но код все равно получится длиннее. И, опять же, если Вы используете свои собственные соглашения по передаче параметров и использованию регистров в ваших модулях на ассемблере, то Вы будете вынуждены писать Ваши функции в соответствии с принятыми Вами соглашениями. А это неизбежно приведет к увеличению кода аналогично тому, как это делается компилятором.

Вот код для IAR (если я ничего не напутал):
Код
crc8iar:            ;Input: r17:r16 buffer; r18 - number of bytes    
                    ;Output: r16 = CRC

        movw    r31:r30,r17:r16
        ldi        r16,0            ;CRC
        ldi        r19,0x8c
crc8iar_1:
        ld        r20,Z+
        ldi        r21,8
crc8iar_2:
        lsr        r16
        brbc    0,crc8iar_3
        eor        r16,r19
crc8iar_3:
        sbrc    r20,0
        eor        r16,r19
        lsr        r20
crc8iar_4:
        dec        r21
        brne    crc8iar_2
        dec        r18
        brne    crc8iar_1

        ret

Добавилась всего одна инструкция:
Код
        movw    r31:r30,r17:r16
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- singlskv   Оптимизация алгоритма на С   Aug 23 2006, 21:50
- - defunct   Вы уверены что у вас считается именно CRC? Попробу...   Aug 24 2006, 00:36
|- - singlskv   Цитата(defunct @ Aug 24 2006, 04:36) Вы у...   Aug 24 2006, 09:41
|- - µµC   Цитата(singlskv @ Aug 24 2006, 13:41) Да ...   Aug 24 2006, 12:41
|- - singlskv   Цитата(µµC @ Aug 24 2006, 16:41) Цитата(s...   Aug 24 2006, 19:35
|- - µµC   Цитата(singlskv @ Aug 24 2006, 23:35) Есл...   Aug 24 2006, 20:20
|- - singlskv   Цитата(µµC @ Aug 25 2006, 00:20) Цитата(s...   Aug 24 2006, 20:45
|- - µµC   Цитата(singlskv @ Aug 25 2006, 00:45) есл...   Aug 24 2006, 21:03
|- - singlskv   Цитата(µµC @ Aug 25 2006, 01:03) Цитата(s...   Aug 24 2006, 21:20
- - KRS   конечно 2 вариант быстрее! дело в организации ...   Aug 24 2006, 07:52
- - vet   Цитата(singlskv @ Aug 24 2006, 01:50) Соб...   Aug 24 2006, 07:56
|- - Old1   Цитата(vet @ Aug 24 2006, 10:56) Цитата(s...   Aug 24 2006, 09:28
||- - µµC   Цитата(singlskv @ Aug 25 2006, 00:29) Луч...   Aug 24 2006, 20:41
|||- - zltigo   Цитата(µµC @ Aug 24 2006, 23:41) Цитата(s...   Aug 24 2006, 21:00
|||- - singlskv   Цитата(zltigo @ Aug 25 2006, 01:00) Быстр...   Aug 24 2006, 21:50
||- - _Bill   Цитата(singlskv @ Aug 25 2006, 15:30) Вот...   Aug 25 2006, 12:59
||- - _Bill   Цитата(singlskv @ Aug 25 2006, 15:30) Вот...   Aug 25 2006, 13:30
||- - singlskv   Цитата(_Bill @ Aug 25 2006, 17:30) Вот ре...   Aug 25 2006, 13:49
|- - singlskv   Цитата(vet @ Aug 24 2006, 14:20) Скомпили...   Aug 24 2006, 19:24
|- - Rst7   Цитата(singlskv @ Aug 24 2006, 22:24) оче...   Aug 25 2006, 06:13
- - Serg79   В таких случаях поступают намного проше, пишут фун...   Aug 25 2006, 06:07
|- - singlskv   Цитата(Serg79 @ Aug 25 2006, 10:07) В так...   Aug 25 2006, 08:24
|- - Rst7   Цитата(singlskv @ Aug 25 2006, 11:24) Ну ...   Aug 25 2006, 08:42
- - TomaT   Эх... у 51-го чудная инструкция есть -- DJNZ   Aug 25 2006, 06:25
|- - Rst7   Цитата(TomaT @ Aug 25 2006, 09:25) Эх... ...   Aug 25 2006, 07:48
- - SpiritDance   Она особенно чудна для конвееров.   Aug 25 2006, 07:23
- - µµC   Приятный алгоритм, возьму на вооружение. IAR - 515...   Aug 25 2006, 15:26
|- - singlskv   Цитата(µµC @ Aug 25 2006, 19:26) Приятный...   Aug 25 2006, 15:38
||- - µµC   Цитата(singlskv @ Aug 25 2006, 19:38) а л...   Aug 25 2006, 16:19
|- - singlskv   Цитата(µµC @ Aug 25 2006, 19:26) Приятный...   Aug 25 2006, 17:15
- - Rst7   Чето слабовато: Код__z char crc8_3(char *buff,...   Aug 26 2006, 05:42
|- - singlskv   Цитата(Rst7 @ Aug 26 2006, 09:42) Чето сл...   Aug 26 2006, 21:29
|- - Rst7   Цитата(singlskv @ Aug 27 2006, 00:29) Хот...   Aug 27 2006, 05:20
|- - Rst7   В досыл... Цитата(singlskv @ Aug 27 2006, 00...   Aug 27 2006, 05:38
- - µµC   А что такое "__z"? Что нужно сделать что...   Aug 27 2006, 09:30
- - Rst7   Цитата(µµC @ Aug 27 2006, 12:30) А что та...   Aug 27 2006, 09:56
- - µµC   Цитата(Rst7 @ Aug 27 2006, 13:56) Понял. ...   Aug 27 2006, 10:10


Reply to this topicStart new topic
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 17:11
Рейтинг@Mail.ru


Страница сгенерированна за 0.01523 секунд с 7
ELECTRONIX ©2004-2016