OSDev

для всех
Текущее время: 28 апр 2024, 02:42

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 36 ]  На страницу 1, 2, 3, 4  След.
Автор Сообщение
 Заголовок сообщения: Об эффективности трансляторов
СообщениеДобавлено: 28 июл 2011, 14:41 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
Сравнил для интереса на небольшом фрагменте кода эффективность двух трансляторов под ARM (конкретнее, под ядро Cortex-M3): GCC 4.5-4.6 и KEIL 4.21 (последний, кто не в курсе, является "официальным" компилятором и средой разработки: фирму KEIL во время оно купила ARM). Исходник такой:

Код:
void  CPU_Init(void)
{
    RCC->CR |= RCC_CR_HSEON | RCC_CR_HSION;
    RCC->AHBENR  = AHB_CLOCK_ENABLE;
    RCC->APB1ENR = APB1_CLOCK_ENABLE;
    RCC->APB2ENR = APB2_CLOCK_ENABLE;
    while ( (RCC->CR & RCC_CR_HSIRDY) == 0 ) ;
    RCC->CFGR = RCC_CFGR_MCO_NOCLOCK  |
                RCC_CFGR_USBPRE_1_5   |
                RCC_CFGR_PLLMUL9      |
                RCC_CFGR_PLLXTPRE_HSE |
                RCC_CFGR_PLLSRC_HSE   |
                RCC_CFGR_ADCPRE_DIV6  |
                RCC_CFGR_PPRE2_DIV1   |
                RCC_CFGR_PPRE1_DIV2   |
                RCC_CFGR_HPRE_DIV1    |
                RCC_CFGR_SW_HSI;
    while ( (RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI ) ;
    FLASH->ACR = FLASH_ACR_LATENCY_2 | FLASH_ACR_PRFTBE;
    while ( (RCC->CR & RCC_CR_HSERDY) == 0 ) ;
    RCC->CR |= RCC_CR_PLLON;
    while ( (RCC->CR & RCC_CR_PLLRDY) == 0 ) ;
    RCC->CFGR = RCC_CFGR_MCO_NOCLOCK  |
                     RCC_CFGR_USBPRE_1_5   |
                     RCC_CFGR_PLLMUL9      |
                     RCC_CFGR_PLLXTPRE_HSE |
                     RCC_CFGR_PLLSRC_HSE   |
                     RCC_CFGR_ADCPRE_DIV6  |
                     RCC_CFGR_PPRE2_DIV1   |
                     RCC_CFGR_PPRE1_DIV2   |
                     RCC_CFGR_HPRE_DIV1    |
                     RCC_CFGR_SW_PLL;
    while ( (RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL ) ;
    GPIOA->CRH = GPIOA_CRH;
    GPIOA->CRL = GPIOA_CRL;
    GPIOB->CRH = GPIOB_CRH;
    GPIOB->CRL = GPIOB_CRL;
    GPIOC->CRH = GPIOC_CRH;
    GPIOC->CRL = GPIOC_CRL;
    GPIOD->CRL = GPIOD_CRL;
    AFIO->MAPR = AFIO_MAPR;
}


Все переменные -- это "неустойчивые" (volatile) структуры с фиксированными адресами, которые являются на самом деле блоками регистров микроконтроллеров семейства STM32F10xxx. Объединение регистров устройств в структуры объясняется особенностью архитектуры ARM: у неё нет непосредственной адресации памяти (чего-то типа MOV [адрес], EAX для IA-32), и любое обращение к памяти выполняется с использованием базового адреса в регистре (например, STR R1, [R5, #12] -- записать содержимое регистра 1 в память по адресу, равному сумме регистра 5 и константы 12).

В обоих случаях использовалась оптимизация -O2 (означающая одно и то же: почти максимальную оптимизацию, за исключением, главным образом, инлайнов; -О3 в данном случае даёт такой же результат).

KEIL выдал такой код:

Код:
KERNEL:00000000 KERNEL_0                                ; Alternative name is 'CPU_Init'
KERNEL:00000000                 LDR     R0, =0x40021000
KERNEL:00000002                 LDR     R1, [R0]
KERNEL:00000004                 ORR.W   R1, R1, #0x10001
KERNEL:00000008                 STR     R1, [R0]
KERNEL:0000000A                 MOVS    R1, #0x15
KERNEL:0000000C                 STR     R1, [R0,#0x14]
KERNEL:0000000E                 MOVS    R1, #0
KERNEL:00000010                 STR     R1, [R0,#0x1C]
KERNEL:00000012                 MOVW    R1, #0x403D
KERNEL:00000016                 STR     R1, [R0,#0x18]
KERNEL:00000018
KERNEL:00000018 loc_18                                  ; CODE XREF: KERNEL:0000001Cj
KERNEL:00000018                 LDR     R1, [R0]
KERNEL:0000001A                 LSLS    R1, R1, #0x1E
KERNEL:0000001C                 BPL     loc_18
KERNEL:0000001E                 LDR     R1, =0x1D8400
KERNEL:00000020                 STR     R1, [R0,#4]
KERNEL:00000022
KERNEL:00000022 loc_22                                  ; CODE XREF: KERNEL:00000028j
KERNEL:00000022                 LDR     R1, [R0,#4]
KERNEL:00000024                 TST.W   R1, #0xC
KERNEL:00000028                 BNE     loc_22
KERNEL:0000002A                 LDR     R2, =0x40022000
KERNEL:0000002C                 MOVS    R1, #0x12
KERNEL:0000002E                 STR     R1, [R2]
KERNEL:00000030
KERNEL:00000030 loc_30                                  ; CODE XREF: KERNEL:00000034j
KERNEL:00000030                 LDR     R1, [R0]
KERNEL:00000032                 LSLS    R1, R1, #0xE
KERNEL:00000034                 BPL     loc_30
KERNEL:00000036                 LDR     R1, [R0]
KERNEL:00000038                 ORR.W   R1, R1, #0x1000000
KERNEL:0000003C                 STR     R1, [R0]
KERNEL:0000003E
KERNEL:0000003E loc_3E                                  ; CODE XREF: KERNEL:00000042j
KERNEL:0000003E                 LDR     R1, [R0]
KERNEL:00000040                 LSLS    R1, R1, #6
KERNEL:00000042                 BPL     loc_3E
KERNEL:00000044                 LDR     R1, =0x1D8400
KERNEL:00000046                 ADDS    R1, R1, #2
KERNEL:00000048                 STR     R1, [R0,#4]
KERNEL:0000004A
KERNEL:0000004A loc_4A                                  ; CODE XREF: KERNEL:00000052j
KERNEL:0000004A                 LDR     R1, [R0,#4]
KERNEL:0000004C                 UBFX.W  R1, R1, #2, #2
KERNEL:00000050                 CMP     R1, #2
KERNEL:00000052                 BNE     loc_4A
KERNEL:00000054                 LDR     R1, =0x40010804
KERNEL:00000056                 LDR     R0, =0x444444B4
KERNEL:00000058                 STR     R0, [R1]
KERNEL:0000005A                 SUBS    R1, R1, #4
KERNEL:0000005C                 LDR     R0, =0xB4B44404
KERNEL:0000005E                 STR     R0, [R1]
KERNEL:00000060                 LDR     R1, =0x40010C04
KERNEL:00000062                 MOV.W   R0, #0x33333333
KERNEL:00000066                 STR     R0, [R1]
KERNEL:00000068                 SUBS    R1, R1, #4
KERNEL:0000006A                 MOV.W   R0, #0x44444444
KERNEL:0000006E                 STR     R0, [R1]
KERNEL:00000070                 LDR     R1, =0x40011000
KERNEL:00000072                 STR     R0, [R1,#4]
KERNEL:00000074                 STR     R0, [R1]
KERNEL:00000076                 LDR     R1, =0x40011400
KERNEL:00000078                 STR     R0, [R1]
KERNEL:0000007A                 LDR     R1, =0x40010000
KERNEL:0000007C                 MOV.W   R0, #0x4000
KERNEL:00000080                 STR     R0, [R1,#4]
KERNEL:00000082                 BX      LR
KERNEL:00000084


А у GCC получилось следующее:

Код:
.text:00000000 cpu__cpu_init
.text:00000000                 PUSH    {R4-R6}
.text:00000002                 MOV     R3, 0x40021000
.text:0000000A                 LDR     R2, [R3]
.text:0000000C                 MOV     R1, R3
.text:0000000E                 ORR.W   R2, R2, #0x10001
.text:00000012                 STR     R2, [R3]
.text:00000014                 MOVS    R2, #0x15
.text:00000016                 STR     R2, [R3,#0x14]
.text:00000018                 MOVS    R2, #0
.text:0000001A                 STR     R2, [R3,#0x1C]
.text:0000001C                 MOVW    R2, #0x403D
.text:00000020                 STR     R2, [R3,#0x18]
.text:00000022
.text:00000022 loc_22                                  ; CODE XREF: cpu__cpu_init+30j
.text:00000022                 LDR     R2, [R1]
.text:00000024                 MOV.W   R3, #0x1000
.text:00000028                 TST.W   R2, #2
.text:0000002C                 MOVT.W  R3, #0x4002
.text:00000030                 BEQ     loc_22
.text:00000032                 LDR     R0, =unk_114
.text:00000034                 MOV     R2, R3
.text:00000036                 LDR     R1, [R0]
.text:00000038                 STR     R1, [R3,#4]
.text:0000003A
.text:0000003A loc_3A                                  ; CODE XREF: cpu__cpu_init+42j
.text:0000003A                 LDR     R3, [R2,#4]
.text:0000003C                 UBFX.W  R3, R3, #2, #2
.text:00000040                 CMP     R3, #0
.text:00000042                 BNE     loc_3A
.text:00000044                 MOVS    R1, #2
.text:00000046                 MOVS    R2, #0
.text:00000048                 BFI.W   R2, R1, #0, #3
.text:0000004C                 BFI.W   R2, R3, #3, #1
.text:00000050                 ORR.W   R2, R2, #0x10
.text:00000054                 MOV.W   R12, #0x2000
.text:00000058                 BFI.W   R2, R3, #5, #1
.text:0000005C                 MOVT.W  R12, #0x4002
.text:00000060                 MOV.W   R1, #0x1000
.text:00000064                 STR.W   R2, [R12]
.text:00000068                 MOVT.W  R1, #0x4002
.text:0000006C
.text:0000006C loc_6C                                  ; CODE XREF: cpu__cpu_init+7Aj
.text:0000006C                 LDR     R2, [R1]
.text:0000006E                 MOV.W   R3, #0x1000
.text:00000072                 TST.W   R2, #0x20000
.text:00000076                 MOVT.W  R3, #0x4002
.text:0000007A                 BEQ     loc_6C
.text:0000007C                 LDR     R2, [R3]
.text:0000007E                 MOV     R1, R3
.text:00000080                 ORR.W   R2, R2, #0x1000000
.text:00000084                 STR     R2, [R3]
.text:00000086
.text:00000086 loc_86                                  ; CODE XREF: cpu__cpu_init+94j
.text:00000086                 LDR     R2, [R1]
.text:00000088                 MOV.W   R3, #0x1000
.text:0000008C                 TST.W   R2, #0x2000000
.text:00000090                 MOVT.W  R3, #0x4002
.text:00000094                 BEQ     loc_86
.text:00000096                 LDR     R1, [R0,#4]
.text:00000098                 MOV     R2, R3
.text:0000009A                 STR     R1, [R3,#4]
.text:0000009C
.text:0000009C loc_9C                                  ; CODE XREF: cpu__cpu_init+A4j
.text:0000009C                 LDR     R3, [R2,#4]
.text:0000009E                 UBFX.W  R3, R3, #2, #2
.text:000000A2                 CMP     R3, #2
.text:000000A4                 BNE     loc_9C
.text:000000A6                 MOV.W   R12, #0x800
.text:000000AA                 MOVW    R6, #0x44B4
.text:000000AE                 MOVW    R5, #0x4404
.text:000000B2                 MOVT.W  R12, #0x4001
.text:000000B6                 MOV.W   R0, #0xC00
.text:000000BA                 MOV.W   R1, #0x1000
.text:000000BE                 MOV.W   R4, #0x1400
.text:000000C2                 MOVT.W  R6, #0x4444
.text:000000C6                 MOVT.W  R5, #0xB4B4
.text:000000CA                 STR.W   R6, [R12,#4]
.text:000000CE                 MOV.W   R2, #0x44444444
.text:000000D2                 STR.W   R5, [R12]
.text:000000D6                 MOVT.W  R0, #0x4001
.text:000000DA                 MOVT.W  R1, #0x4001
.text:000000DE                 MOVS    R3, #0
.text:000000E0                 MOVT.W  R4, #0x4001
.text:000000E4                 MOV.W   R12, #0x33333333
.text:000000E8                 STR.W   R12, [R0,#4]
.text:000000EC                 MOVT.W  R3, #0x4001
.text:000000F0                 STR     R2, [R0]
.text:000000F2                 STR     R2, [R1,#4]
.text:000000F4                 STR     R2, [R1]
.text:000000F6                 STR     R2, [R4]
.text:000000F8                 MOV.W   R2, #0x4000
.text:000000FC                 STR     R2, [R3,#4]
.text:000000FE                 LDR     R2, [R3,#4]
.text:00000100                 STR     R2, [R3,#4]
.text:00000102                 POP     {R4-R6}
.text:00000104                 BX      LR
.text:00000106


Налицо очень большая разница в длине кода: 130 байтов у транслятора KEIL и 262 байта у GCC. Если заняться анализом кода, то можно выделить четыре глупости, совершаемые GCC:

1) Он плохо помнит содержимое регистров процессора. Например, загрузив в самом начале базовый адрес RCC в регистр 3 (смещение 2), он почти сразу пересылает его в регистр 1 (смещение C), вместо того, чтобы продолжать пользоваться регистром 3. Аналогичным образом он поступает и дальше. Как следствие, ему не хватило рабочих регистров (R0-R3, R12), и он сохранил в стеке ещё три регистра (R4-R6).

2) Он вставляет фактически бессмысленные команды внутрь циклов (смещения 22, 6C, 86 -- MOVы, которые надо было бы вынести из циклов).

3) Иногда он зачем-то вновь загружает эти значения и сразу же опять записывает (пара LDR-STR по смещению FE-100). Помимо раздувания кода, это может привести вообще к некорректной работе программы: это же не обычные ячейки памяти, а регистры устройств. При каких условиях генерируется подобный код, пока неясно.

4) Наконец, он банально глупо грузит константы, собирая их по кусочкам с помощью MOVов (со смещения A6) вместо прямой загрузки из памяти с помощью LDR, как это делает KEIL (со смещения 54).

В итоге получаем жутко раздутый код (в 2 раза длиннее, чем надо), да к тому же потенциально некорректно выполняющийся из-за п. 3 (в данном конкретном случае к неприятным последствиям это не приведёт, но...).

В общем, похоже, не зря KEIL стоит больших денег (несколько тыщ евро): код корректный, заметно более качественный, плюс в комплекте IDE (пускай и не верх совершенства, но у GCC вообще ничего нет, надо использовать сторонние вещи), всякие там заголовочные файлы под различные контроллеры...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Об эффективности трансляторов
СообщениеДобавлено: 28 июл 2011, 14:56 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
Вдогонку к предыдущему. По моей просьбе Grindars странслировал этот же код с использованием CLANG или как там его. Получилось вот что:

Код:
   0:   f241 0000       movw    r0, #4096       ; 0x1000
   4:   2215            movs    r2, #21
   6:   f2c4 0002       movt    r0, #16386      ; 0x4002
   a:   6801            ldr     r1, [r0, #0]
   c:   f041 1101       orr.w   r1, r1, #65537  ; 0x10001
  10:   6001            str     r1, [r0, #0]
  12:   f241 0114       movw    r1, #4116       ; 0x1014
  16:   f2c4 0102       movt    r1, #16386      ; 0x4002
  1a:   600a            str     r2, [r1, #0]
  1c:   f241 011c       movw    r1, #4124       ; 0x101c
  20:   2200            movs    r2, #0
  22:   f2c4 0102       movt    r1, #16386      ; 0x4002
  26:   600a            str     r2, [r1, #0]
  28:   f241 0118       movw    r1, #4120       ; 0x1018
  2c:   f244 023d       movw    r2, #16445      ; 0x403d
  30:   f2c4 0102       movt    r1, #16386      ; 0x4002
  34:   600a            str     r2, [r1, #0]
  36:   6801            ldr     r1, [r0, #0]
  38:   f011 0f02       tst.w   r1, #2
  3c:   d0fb            beq.n   36 <CPU_Init+0x36>
  3e:   f241 0104       movw    r1, #4100       ; 0x1004
  42:   f248 4200       movw    r2, #33792      ; 0x8400
  46:   f2c4 0102       movt    r1, #16386      ; 0x4002
  4a:   f2c0 021d       movt    r2, #29
  4e:   600a            str     r2, [r1, #0]
  50:   680a            ldr     r2, [r1, #0]
  52:   f012 0f0c       tst.w   r2, #12
  56:   d1fb            bne.n   50 <CPU_Init+0x50>
  58:   f242 0200       movw    r2, #8192       ; 0x2000
  5c:   2312            movs    r3, #18
  5e:   f2c4 0202       movt    r2, #16386      ; 0x4002
  62:   6013            str     r3, [r2, #0]
  64:   6802            ldr     r2, [r0, #0]
  66:   f412 3f00       tst.w   r2, #131072     ; 0x20000
  6a:   d0fb            beq.n   64 <CPU_Init+0x64>
  6c:   6802            ldr     r2, [r0, #0]
  6e:   f042 7280       orr.w   r2, r2, #16777216       ; 0x1000000
  72:   6002            str     r2, [r0, #0]
  74:   6802            ldr     r2, [r0, #0]
  76:   f012 7f00       tst.w   r2, #33554432   ; 0x2000000
  7a:   d0fb            beq.n   74 <CPU_Init+0x74>
  7c:   f248 4002       movw    r0, #33794      ; 0x8402
  80:   f2c0 001d       movt    r0, #29
  84:   6008            str     r0, [r1, #0]
  86:   6808            ldr     r0, [r1, #0]
  88:   f000 000c       and.w   r0, r0, #12
  8c:   2808            cmp     r0, #8
  8e:   d1fa            bne.n   86 <CPU_Init+0x86>
  90:   f640 0004       movw    r0, #2052       ; 0x804
  94:   f244 41b4       movw    r1, #17588      ; 0x44b4
  98:   f2c4 0001       movt    r0, #16385      ; 0x4001
  9c:   f2c4 4144       movt    r1, #17476      ; 0x4444
  a0:   6001            str     r1, [r0, #0]
  a2:   f640 0000       movw    r0, #2048       ; 0x800
  a6:   f244 4104       movw    r1, #17412      ; 0x4404
  aa:   f2c4 0001       movt    r0, #16385      ; 0x4001
  ae:   f2cb 41b4       movt    r1, #46260      ; 0xb4b4
  b2:   6001            str     r1, [r0, #0]
  b4:   f640 4004       movw    r0, #3076       ; 0xc04
  b8:   f04f 3133       mov.w   r1, #858993459  ; 0x33333333
  bc:   f2c4 0001       movt    r0, #16385      ; 0x4001
  c0:   6001            str     r1, [r0, #0]
  c2:   f640 4100       movw    r1, #3072       ; 0xc00
  c6:   f04f 3044       mov.w   r0, #1145324612 ; 0x44444444
  ca:   f2c4 0101       movt    r1, #16385      ; 0x4001
  ce:   6008            str     r0, [r1, #0]
  d0:   f241 0104       movw    r1, #4100       ; 0x1004
  d4:   f2c4 0101       movt    r1, #16385      ; 0x4001
  d8:   6008            str     r0, [r1, #0]
  da:   f241 0100       movw    r1, #4096       ; 0x1000
  de:   f2c4 0101       movt    r1, #16385      ; 0x4001
  e2:   6008            str     r0, [r1, #0]
  e4:   f241 4100       movw    r1, #5120       ; 0x1400
  e8:   f2c4 0101       movt    r1, #16385      ; 0x4001
  ec:   6008            str     r0, [r1, #0]
  ee:   2004            movs    r0, #4
  f0:   f44f 4180       mov.w   r1, #16384      ; 0x4000
  f4:   f2c4 0001       movt    r0, #16385      ; 0x4001
  f8:   6001            str     r1, [r0, #0]
  fa:   4770            bx      lr


Код вроде корректный и короче GCCшного, хотя и существенно больше KEILовского.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Об эффективности трансляторов
СообщениеДобавлено: 28 июл 2011, 16:14 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
Поэкскрементировал тут и получил следующие результаты...

1) Неверный код (загрузка только что записанного значения и его повторная запись) генерируется при любой оптимизации, кроме -O0, т.е. вызван какой-то ошибкой в оптимизаторе. Обойти эту генерацию можно, если нужную константу сначала присвоить промежуточной переменной, а потом выполнить присваивание этой переменной "неустойчивому" полю, т.е. вместо

Код:
Volatile_Reg = const;


писать примерно такое:

Код:
temp = const;
Volatile_Reg = temp;


2) Наиболее компактный (176 байт) и одновременно быстрый код генерируется при оптимизации -Os, т.е. по размеру.

Кстати говоря, алгоритмически одинаковый код на Си и Аде даёт одинаковый машинный код, но это как раз вполне ожидаемо: оптимизатор и кодогенератор же у них общий, различаются только фронт-энды.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Об эффективности трансляторов
СообщениеДобавлено: 28 июл 2011, 22:46 
Аватара пользователя

Зарегистрирован: 14 мар 2011, 12:31
Сообщения: 970
Откуда: Дагоба
SII писал(а):
Налицо очень большая разница в длине кода: 130 байтов у транслятора KEIL и 262 байта у GCC. Если заняться анализом кода, то можно выделить четыре глупости, совершаемые GCC...
В общем, похоже, не зря KEIL стоит больших денег (несколько тыщ евро): код корректный, заметно более качественный...

А я всегда говорил, — не всё то благо, что GNUсно распространяемое. Самые качественные продукты обычно платные.

_________________
Yet Other Developer of Architecture.
The mistery of Yoda’s speech uncovered is:
Just an old Forth programmer Yoda was.

<<< OS Boot Tools. >>>


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Об эффективности трансляторов
СообщениеДобавлено: 28 июл 2011, 22:50 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
Yoda писал(а):
А я всегда говорил, — не всё то благо, что GNUсно распространяемое. Самые качественные продукты обычно платные.


Вот-вот. По крайней мере, если речь идёт о действительно крупных и сложных продуктах.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Об эффективности трансляторов
СообщениеДобавлено: 29 июл 2011, 02:12 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
А теперь наткнулся на настолько неверную кодогенерацию, что трансляция вообще не проходит: валится ассемблер:

C:\TEMP\ccldORbK.s: Assembler messages:
C:\TEMP\ccldORbK.s:64: Error: immediate value out of range -- `movteq r7,-4096'
C:\TEMP\ccldORbK.s:66: Error: incorrect condition in IT block -- `bfcne r6,#16,#16'
C:\TEMP\ccldORbK.s:68: Error: instruction not allowed in IT block -- `and r2,r2,#8192'

C:\TEMP\ccvXA4Sd.s: Assembler messages:
C:\TEMP\ccvXA4Sd.s:62: Error: immediate value out of range -- `movteq r5,-4096'
C:\TEMP\ccvXA4Sd.s:64: Error: incorrect condition in IT block -- `bfcne r4,#16,#16'
C:\TEMP\ccvXA4Sd.s:66: Error: IT falling in the range of a previous IT block -- `ite eq'
C:\TEMP\ccvXA4Sd.s:67: Error: thumb conditional instruction should be in IT block -- `streq r5,[r3,#16]'
C:\TEMP\ccvXA4Sd.s:69: Error: thumb conditional instruction should be in IT block -- `strne r4,[r3,#16]'

В общем, качество GCC как транслятора, мягко говоря, очень и очень невысокое со всех точек зрения. Одно слово: опенсорц. Жаль, под АРМ коммерческие компиляторы -- исключительно Си/Си++, Паскаля/Модулы/Оберона/Ады нет...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Об эффективности трансляторов
СообщениеДобавлено: 31 июл 2011, 01:53 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
Вручную закодировал ту же процедурку на ассемблере. Вместе с константами в памяти заняла 154 байта, у Кейла -- 160 (размер выше, равный 130 байтам, был дан без учёта констант). Выигрыш, как видим, есть, но незначительный. Правда, и сам код тупо прямолинейный; в более сложных случаях ручное программирование даёт больше выгоды (естественно, ценой затрат большего времени).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Об эффективности трансляторов
СообщениеДобавлено: 31 июл 2011, 09:57 

Зарегистрирован: 21 сен 2007, 17:24
Сообщения: 1088
Откуда: Балаково
GCC под x86 оптимизирует гораздо лучше. Может быть проблема в кросскомпиляции - не может один оптимизатор идеально подходить под все процессоры. Софтина, заточенная под конкретную архитектуру всегда лучше.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Об эффективности трансляторов
СообщениеДобавлено: 31 июл 2011, 11:57 
Аватара пользователя

Зарегистрирован: 16 май 2007, 23:46
Сообщения: 1126
По моему я где-то читал. Что официально GCC под arm не оптимизирует.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Об эффективности трансляторов
СообщениеДобавлено: 31 июл 2011, 14:29 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
pavia писал(а):
По моему я где-то читал. Что официально GCC под arm не оптимизирует.


Если на то пошло, оптимизация делится на два вида: машинно-независимую и машинно-зависимую. Даже если вторая напрочь отсутствует, первая должна работать в любом случае. Ну и, кроме того, никакое отсутствие оптимизации не может порождать неверный код. Я же убедился, что без оптимизации (ключ -O0) GCC выдаёт корректный, хотя и очень неэффективный код, а вот при включении любой оптимизации код становится некорректным для некоторых случаев (если обращение идёт к регистрам устройств, а не к обычной памяти), причём мне удалось-таки подобрать способ, как обойти эту неверную генерацию. В общем, дело не в этом.

Himik писал(а):
GCC под x86 оптимизирует гораздо лучше. Может быть проблема в кросскомпиляции - не может один оптимизатор идеально подходить под все процессоры. Софтина, заточенная под конкретную архитектуру всегда лучше.


Абсолютно согласен. Просто данный пример развеивает сразу два мифа, бытующих у поклонников свободного ПО:

1) основное инструментальное средство "борцов за свободу", коим является GCC, -- эффективное решение на любой платформе (как видим, оно откровенно неэффективно даже на одной из самых популярных и распространённых платформ);
2) Линух -- эффективная ОС (поскольку она компилируется с помощью GCC, то, даже без учёта "личных качеств" самой системы "в вакууме", она будет неэффективной на любой платформе, для которой GCC порождает плохой код).

Ну а как итог: я лишний раз убедился, что инструментальное ПО должно затачиваться под конкретную платформу. Хотя нельзя сказать, что подход GCC абсолютно неверен, однако его реализация, как обычно, далека даже от "тройки". Действительно, можно разделить фронт-энд (транслятор с исходного языка в промежуточное представление), машинно-независимый оптимизатор (работающий только с этим промежуточным представлением) и бэк-энд (машинно-зависимый оптимизатор и генератор объектного/ассемблерного кода), получив при этом хорошие результаты (поскольку эффективные трансляторы, по сути, так и работают, только "линия раздела" находится внутри них), но делать это надо аккуратно, уделяя большое внимание деталям, а также тщательно документируя всё и вся. В случае с GCC этого нет: его исходники просто ужасны, документация крайне неполна и т.д. Неудивительно, что на выходе имеем столь низкое качество. Ну а его разработчики, вместо того, чтобы доводить его до ума, всё впихивают и впихивают новые прибамбасы (зачем, например, какая-то оптимизация циклов graphite, если у них оптимизатор впихивает в циклы лишние команды, которые однозначно должны находиться вне цикла? лучше б доделали простые виды оптимизации, чем выдумывать сложные). Кроме того, похоже, GCC никто толком не тестирует ни на чём хоть малость нестандартном...


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 36 ]  На страницу 1, 2, 3, 4  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 16


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB