Переменная длина массива накладных расходов в C ++? - PullRequest
13 голосов
/ 03 декабря 2010

Глядя на этот вопрос: Почему компилятору C / C ++ нужно знать размер массива во время компиляции? мне пришло в голову, что у разработчиков компилятора должно было быть несколько раз, чтобы промокнуть ноги сейчас (это часть стандарта C99, это 10 лет назад) и обеспечивает эффективные реализации.

Однако все же кажется (из ответов) дорогостоящим.

Это меня как-то удивляет.

Конечно, я понимаю, что статическое смещение намного лучше динамического с точки зрения производительности, и в отличие от одного предложения, я бы на самом деле не дал компилятору выполнить выделение массива кучи, поскольку это, вероятно, будет стоить еще дороже [ это не было измерено;)]

Но я все еще удивлен предполагаемой стоимостью :

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

Конечно, возникает вопрос о нескольких VLA, и мне было интересно, сработает ли выделенный стек VLA. Это означает, что VLA будет представлен счетчиком и указателем (следовательно, известных размеров) и фактической памятью, занятой во вторичном стеке, используемом только для этой цели (и, следовательно, действительно в стеке).

[перефразируя]

Как VLA реализованы в gcc / VC ++?

Неужели стоимость действительно впечатляет?

[перефразировать конец]

Мне кажется, что это может быть лучше, чем, скажем, использование vector, даже с существующими реализациями, поскольку вы не несете затрат на динамическое распределение (за счет отсутствия изменения размера).

EDIT:

Здесь есть частичный ответ здесь , однако сравнение VLA с традиционными массивами кажется несправедливым. Если бы мы знали размер заранее, то нам не понадобился бы VLA. В том же вопросе AndreyT дал несколько указаний относительно реализации, но это не так точно, как хотелось бы.

Ответы [ 2 ]

4 голосов
/ 04 декабря 2010

Как VLA реализованы в gcc / VC ++?

AFAIK VC ++ не реализует VLA.Это компилятор C ++, и он поддерживает только C89 (без VLA, без ограничений).Я не знаю, как gcc реализует VLA, но самый быстрый способ - сохранить указатель на VLA и его размер в статической части кадра стека.Таким образом, вы можете получить доступ к одному из VLA с производительностью массива постоянного размера (это последний VLA, если стек растет вниз, как в x86 (разыменование [указатель стека + индекс * размер элемента + размер последних временных нажатий]),и первый VLA, если он растет вверх (разыменование [указатель стека фрейма + смещение от стека фрейма + индекс * размер элемента])).Всем остальным VLA потребуется еще одно косвенное обращение, чтобы получить их базовый адрес из статической части стека.

[ Редактировать: Также при использовании VLA компилятор не может опустить указатель на основе стека и фрейма, который в противном случае является избыточным, поскольку все смещения от указателя на стек могут быть вычислены во время компиляциивремя.Таким образом, у вас есть один менее бесплатный регистр.- end edit ]

Неужели стоимость действительно впечатляет?

Не совсем.Более того, если вы не используете его, вы не платите за него.

[ Редактировать: Возможно, более правильный ответ будет: По сравнению с чем?По сравнению с вектором, выделенным для кучи, время доступа будет таким же, но распределение и освобождение будут быстрее.- конец редактирования ]

0 голосов
/ 04 декабря 2010

Если бы это было реализовано в VC ++, я бы предположил, что команда компилятора использовала бы какой-то вариант _alloca(size). И я думаю, что стоимость эквивалентна использованию переменных с выравниванием более 8 байтов в стеке (например, __m128); компилятор должен где-то хранить исходный указатель стека, а для выравнивания стека требуется дополнительный регистр для хранения невыровненного стека.

Таким образом, накладные расходы в основном являются дополнительным косвенным указанием (вы должны где-то хранить адрес VLA) и регистрировать давление из-за сохранения исходного диапазона стека где-то также.

...