Насколько хорошо Ada может оптимизировать массивы статических констант?

Допустим, я объявляю массив постоянных значений для использования в качестве таблицы поиска:

function Square(num : Integer) return Integer is
use Ada.Text_IO;
type LookupItemsRange is range 1..10;
type LookupTable is array(LookupItemsRange) of integer;
A : constant LookupTable := (2312,2,3,4,5,6,7,8,9, 10);
begin
    Sqr := A(1);
    Sqr := 2 * A(2);
    return Sqr;
end Square;

LookupTable не должна занимать место. Компилятор должен иметь возможность заменить доступ к массиву фактическими встроенными значениями. При самых высоких настройках оптимизации вот что дает Ада:

_ada_square:
        li      a0,4                #,
        ret     

Я планирую заменить большое количество избыточного кода MCU более чистой реализацией таблицы поиска. Поскольку ресурсы микроконтроллера ограничены, я хотел бы избежать ненужного распределения и индексации.

При каких обстоятельствах Ада выделит массив или я в полной безопасности?

Для "При каких обстоятельствах..."; если индекс массива неизвестен во время компиляции (например, получен из пользовательского ввода или как Foo := A(random_number);), любому компилятору (для любого языка) будет сложно избежать выделения массива; особенно если в данных нет обнаруживаемой закономерности (как во всех, кроме первого элемента в (2312,2,3,4,5,6,7,8,9, 10)).

Brendan 20.10.2022 10:20

Но постоянный массив будет размещен в ПЗУ, а не в ОЗУ, а у микроконтроллеров обычно намного больше ПЗУ. Мои цифровые часы (на Аде) умещаются под килобайт (LUT и все такое) памяти программ.

user_1818839 22.10.2022 22:34
Загадки Python - Генерация простых чисел!
Загадки Python - Генерация простых чисел!
Обычно существует несколько способов решения задач даже пограничной сложности. Как же определить оптимальное и эффективное решение?
5
2
248
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

  1. Это зависит от вашего компилятора и опций компилятора.
  2. Как вы продемонстрировали, любой компилятор, который вы используете, отлично справляется с оптимизацией.
  3. В Ada Outperforms Assembly: Case Study, представленном в 1992 году, компилятор Ada (83) создавал более быстрый код, чем ассемблер, оптимизированный командой экспертов. Предположительно, за последние 30 с лишним лет оптимизаторы стали еще лучше, поэтому беспокоиться о подобных вещах, при отсутствии измерений, показывающих обратное, — пустая трата времени.

Для традиционных приложений вы действительно правы. Для микроконтроллеров с ограниченным объемом памяти, где время выполнения инструкций решает все, это становится критическим. Я хорошо знаю превосходную оптимизацию Ады, но есть операции, в которых компилятор выделяет массив и/или генерирует инструкции для доступа к нему.

ATL_DEV 20.10.2022 21:58

Очевидно, что оптимизация, о которой вы говорите, может произойти только в том случае, если все, что связано с массивом, статично, а это неверно для справочной таблицы. Дело в том, что если вы можете сделать вещи статичными, вы можете положиться на компилятор, чтобы оптимизировать их; а когда вы не можете, вы можете положиться на то, что компилятор проделает хорошую работу по оптимизации того, что он не может оптимизировать.

Jeffrey R. Carter 21.10.2022 10:48
Ответ принят как подходящий

Таким образом, для спецификации языка Ада вы не получите гарантии для объектов массива. Ада начинает догонять constexpr в новейшем грядущем выпуске (Ada2022), но будет предоставлять аналогичное свойство (Static в Аде) функциям-выражениям (представьте, что они аналогичны функциям constexpr, но с немного другими ограничениями). .

Поэтому, если вы не возражаете полагаться на поставщика вашего компилятора, то массив, скорее всего, будет работать нормально (но не гарантируется). Если вам нужна дополнительная языковая поддержка оптимизации, вам нужно будет имитировать массив, используя функции выражения с набором статических аспектов (в последнем компиляторе). Для статического ввода функция статического выражения даст статический результат (опять же Static в Ada, а не static в C++, больше похоже на constexpr).

function Square return Integer is

    type Lookup_Items_Range is range 1..10;

    function A(Index : Lookup_Items_Range) return Integer is 
        (case Index is
            when 1 => 2312,
            when 2 => 2,
            when 3 => 3,
            when 4 => 4,
            when 5 => 5,
            when 6 => 6,
            when 7 => 7,
            when 8 => 8,
            when 9 => 9,
            when 10 => 10
         ) 
    with Static;

    Sqr : Integer;

begin

    Sqr := A(1);
    Sqr := 2 * A(2);
    return Sqr;
    
end Square;

Это немного более многословно, чем использование массива, но имеет языковую поддержку, что действительно важно в некоторых областях встроенного программирования. Обратите внимание, что большинству последних компиляторов потребуется переключатель для включения этой функции, поскольку она такая новая, но обычно они сообщают вам об этом переключателе в сообщении об ошибке. Я протестировал на godbolt с GNAT 12.1, и он скомпилирован с правильным переключателем.

Хотя функция статического выражения, скорее всего, будет скомпилирована по желанию в этом контексте, static используется в (необычном) смысле Ады — определяемом во время компиляции — поэтому я думаю, что для этого подхода не может быть больше гарантий, чем для LUT (который , в моем простом эксперименте работает как надо даже на -O1).

Simon Wright 05.11.2022 21:48

Другие вопросы по теме