2010-12-03 2 views
12

Глядя на этот вопрос: Why does a C/C++ compiler need know the size of an array at compile time ?, мне пришло в голову, что разработчики компилятора должны были иметь несколько раз, чтобы получить свои ноги теперь (это часть стандарта C99, это 10 лет назад) и обеспечивают эффективные реализации.Накладные расходы переменной длины в C++?

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

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

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

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

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

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

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

Как Власа реализованы в GCC/VC++?

Действительно ли это действительно впечатляет?

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

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

EDIT:

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

+0

@Matthieu M. Deleted. Я должен думать о чем-то другом. – 2010-12-03 09:06:28

+0

@Matthieu: вы думаете, кажется мне здоровым ... VLA предлагает только накладные расходы, когда их больше 1 (просто поместив их «после» элементов известного размера, а затем может быть указатель или дополнительная настройка в стек известного знака-смещения, чтобы указать, где начинаются последующие VLA. Не удается увидеть второй стек, который помогает вообще. – 2010-12-03 09:19:14

ответ

2

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

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

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

Является ли стоимость действительно так впечатляет?

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

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

0

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

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

Смежные вопросы