Design: Обоснование инструкции по хранению в памяти

Созданный на 22 июл. 2020  ·  42Комментарии  ·  Источник: WebAssembly/design

Мне трудно понять логику порядка операндов в стеке операндов для инструкций хранилища в памяти. Это обычная практика, когда кто-то выполняет присвоение, чтобы сначала вычислить исходное значение, затем целевое значение, а затем выполнить сохранение исходного значения в ячейке памяти целевых значений. Однако инструкции сохранения ожидают операнды в стеке в обратном порядке. Сверху находится исходное значение, а в качестве второго значения - смещение. Это означает, что нужно сначала вычислить местоположение смещения целевой памяти, затем исходное значение или после того, как они будут правильно оценены (источник -> цель), чтобы поменять местами два верхних значения перед инструкцией сохранения. В общем случае нет никакого обходного пути, потому что нет инструкций для сохранения непосредственно в локальных переменных без помощи стека операндов. Таким образом, для каждого отдельного хранилища памяти, которое является последней операцией присвоения одного значения другому, требуется дополнительная работа. Есть ли необходимость в инструкциях по хранению в памяти, которые будут ожидать порядок операндов [значение] [смещение вверху]? Или штраф должен быть оплачен за каждый такой нормальный оценочный заказ.

Самый полезный комментарий

@verbessern, это здорово, что вы увлечены тем, чтобы сделать Wasm настолько хорошим, насколько это возможно, но мы должны помнить, что это обсуждение касается технической проблемы с крошечным уголком дизайна спецификации. Пожалуйста, отдайте должное @tlively за то, что

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

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

  • Любой генератор, который проходит через граф потока данных / представление SSA (как это делает LLVM) на пути к Wasm, не будет заботиться о деталях того, как подключен порядок аргументов, потому что это будет обрабатываться общим способом во время опускание до стекового представления.
  • Что касается удобочитаемости, как я думаю, @titzer имел в
    (t.store (addr_calc) (value_calc))
    который визуально отражает
    addr_calc := value_calc
    на языке высокого уровня.

Совершенно очевидно, что нынешний дизайн имеет недостатки. Вопрос в том, лучше ли для языка

  1. ничего не делать и принять незначительный недостаток
  2. ввести swap
  3. ввести t.store_ с замененными аргументами

Я склоняюсь против (3), потому что нам придется делать то же самое для каждого будущего варианта store (например, если мы определим первоклассные воспоминания или объект heap GC). Я был бы доволен либо (1), либо (2). В идеальном мире, возможно, store было бы спроектировано иначе, но сейчас мы не можем сломать веб-совместимость.

Все 42 Комментарий

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

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

Ах .... ах ... Одна проблема здесь, одна там, и прыжок ... потеря скорости в конце. Это напомнило мне об отсутствующей инструкции по дублированию.

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

Хороший момент, на большинстве языков порядок гарантирован. Но если информации достаточно для генерации адреса без побочных эффектов, вы можете сначала поместить ее в стек. Если нет, вам нужно сохранить его в локальном хранилище: например, https://godbolt.org/z/K79bqo.

Но я был бы удивлен, если бы это проблема производительности; как и в случае с dup , стоимость будет оплачена только интерпретатором или базовым компилятором wasm. Я написал для этого небольшой тест:

(import "" "addr" (func $addr (result i32)))
(import "" "value" (func $value (result i32)))
(memory 1)

(func (export "a")
  (local i32)
  call $addr
  local.set 0
  call $value
  local.get 0
  i32.store)

(func (export "b")
  (local i32)
  call $value
  call $addr
  i32.store)

Код, который генерирует v8, практически идентичен, за исключением того, что функции вызываются в обратном порядке.

Имена @binji value и addr в приведенном выше коде отображаются в перевернутом виде, но пункт о сгенерированном коде должен быть одинаково допустимым.

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

Я согласен с @verbessern, хотя порядок, который у нас есть, немного странный ... есть ли обстоятельства, при которых текущий порядок лучше? Почему его выбрали? Один из примеров, который я могу представить, - это когда вы хотите многократно использовать большую часть вычисления адреса и заполнять его простыми скалярами, например, для инициализации структуры:

(complex address calculation)
dup
i32.const 1
i32.store offset=0
i32.const 2
i32.store offset=4

@aardappel ой, ты прав. Я всегда путаю порядок. :-)

Почему его выбрали?

Не уверен, но похоже, что это был порядок возврата к первоначальной реализации ML (август 2015 г.): https://github.com/rossberg/wasm/blob/master/src/eval.ml#L165

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

В то время я просто следил за прототипом V8 от @titzer . Так что, возможно, он знает подоплеку.

И это, возможно, самая большая проблема, которую я знаю о веб-сборке. Предположение, что реализация чего-то где-то является законом. Я во многих местах высказывался (и получил свои отрицательные голоса), что это создает больше проблем, чем решает. Веб-сборка - это уникальный (насколько мне известно) байт-код, и каждая из его функций должна быть логически продумана независимо от того, что было где-то реализовано. Другой пример: нет инструкции как i32.not_equal_z , которая заставляет генераторы выдавать i32.const 0 i32.not_equal , это не имеет большого значения, потому что некоторые среды выполнения оптимизируют ее как asm jnz , но вот мы снова, весь мир не та реализация. Это, в свою очередь, заставляет все среды выполнения вести себя одинаково или просто работать медленнее.

Что касается примера dup с @binji , я утверждаю, что это не то, что он не может быть оптимизирован, а то, что не должно быть необходимости оптимизировать его. Вес выполнения для инструкций local.get / set никогда не будет равен нулю, и зачем платить такую ​​цену, если единственная инструкция, которая логично существует в стековой машине, действительно может существовать. Это просто поднимает планку для каждого времени выполнения, или снова ... просто медленнее.

Пример @aardappel классный (с примечанием, что на данный момент нет инструкции dup ), и что для этого потребуется, чтобы одна использовала локальную переменную, а это, в свою очередь, заставит вас это сделать (если порядок операндов был естественным):

(complex address calculation)
local.set 0
i32.const 1
local.get 0
i32.store offset=0
i32.const 2
local.get 0
i32.store offset=4

если была доступна инструкция dup , тогда стек может переполниться множеством dups , так как с кодом вверх не будет (и количество инструкций для многих полей совпадает с +2, но вы выиграть длину стека)

Я не удивлюсь, если обнаружу, что это относится к тому времени, когда все было s-выражениями, поскольку естественный порядок аргументов есть (store addr val), который переводится в (push addr) (push val) (store) in stack- Мир.

@verbessern :

И это, возможно, самая большая проблема, которую я знаю о веб-сборке. Предположение, что реализация чего-то где-то является законом.

Такого предположения нет, даже наоборот. Первоначальный дизайн обсуждался и дорабатывался группой в течение 1,5 лет. Было внесено много изменений и дополнений, просто никто в то время не предлагал что-то еще по этому конкретному аспекту.

@taralx :

Я не удивлюсь, если обнаружу, что это относится к тому времени, когда все было s-выражениями, поскольку естественный порядок аргументов есть (store addr val), который переводится в (push addr) (push val) (store) in stack- Мир.

Ах да, действительно, это, вероятно, настоящее объяснение. Wasm начинал как язык, основанный на выражениях (даже до того, как у нас появился текстовый формат), в некоторой степени вдохновленный структурой asm.js. Только позже мы переосмыслили это как стековую машину с минимальными изменениями, так что это просто перенесено как есть.

@rossberg Я буду учитывать, что «существующая где-то функция распространилась не потому, что она потребовала бы рефакторинга кода существующих проектов, а потому, что никто этого не заметил, несмотря на свои лучшие намерения»

Другой пример: нет такой инструкции как i32.not_equal_z, которая заставляет генераторы выдавать i32.const 0 i32.not_equal

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

Когда вы на нем, br_if_not также отсутствует и требует дополнительной работы, так же, как i32.not_equal_z , то же самое, что и i32.not . Тест на ненулевое значение, вероятно, самый распространенный из когда-либо вычисляемых тестов. Примерно 10 лет назад я где-то читал статью об инструкциях по сборке Intel и их кодах операций, что, если коды операций были «правильно» назначены, это ускорило бы время выполнения всего и уменьшило бы размер всех исполняемых файлов. В этом смысле, ваш покорный слуга, выпустил выпуск №1308.

пс. Лично мне нравятся богатые API-интерфейсы, но это сомнительно, следует ли добавлять больше инструкций или рассматривать оптимизацию этих общих случаев как «нормальную» и «ожидаемую».

Если в наши дни написание WAT от руки вызывает беспокойство, есть возможность добавить некоторые инструкции исключительно для поверхностного улучшения языка. WAT по существу имеет isEqual , isMore , isLess и isZero дополненные notEqual , notMore и notLess , без инструкции, что означает notZero . Инструкция br_if_not (или br_unless ) также будет иметь смысл, независимо от производительности, размера кода и т. Д., Просто потому, что она делает WAT более приятным.

Порядок выбран не случайно. Сначала идет адрес, затем значение хранилища, потому что оно наиболее точно соответствует естественному порядку оценки слева направо для многих языков, например, *ptr = val [1]. Очень часто на ассемблере сначала записывают цель перемещения, например, mov [%rax], %rbx . Также очень часто в IR компилятора сначала указывается адрес, а затем значение. Таким образом, другой путь пошел бы против всех трех случаев и, таким образом, привел бы к путанице.

[1] Правила порядка вычисления C сложны и включают точки последовательности, но почти все реализации следуют порядку вычисления слева направо, если у них нет действительно веской причины не делать этого. И, конечно же, в большинстве других существующих языков есть строгие правила слева направо.

Я думаю, что swap - хорошая сокращенная инструкция, которую мы должны рассмотреть возможность добавления в Wasm в подобных ситуациях.

@titzer Я думал (поправьте меня, если я ошибаюсь), что C ++ и многие другие языки (ваш аргумент 1) сначала оценивают источник, а затем цель. Это означает, что любой язык подобного рода при компиляции в wasm должен будет проявить особую осторожность, чтобы переключить операнды. Этот пример для языка ассемблера (аргумент 2) вряд ли верен, потому что это чистый синтаксис, он не предписывает какой-либо фактический порядок оценки, как на самом деле порядок источник / цель в wasm. По аргументу 3 у меня нет информации, но, может быть, вы поделитесь, где находится опрос, посвященный «очень распространенному» аргументу?

int k, j;
int &f1(void) { message("a"); return k; }
int &f2(void) { message("b"); return j; }

main
  f1() = f2();

Этот псевдо-C ++ странным образом издает «ба» на моей стороне. Проверьте это: https://en.cppreference.com/w/cpp/language/operator_precedence номер 16 в таблице оператор присваивания.

@verbessern Это было определено только для C ++, начиная с C ++ 17 . Но я не согласен с тем, что это требует дополнительной работы для большинства компиляторов. Компиляторам уже приходится иметь дело с произвольными случаями создания и использования двух значений в порядке FIFO с побочными эффектами, которые предотвращают перемещение производящих вычислений друг за другом, и в этом отношении в хранилищах нет ничего особенного.

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

@tlively Вы утверждаете, что C ++ 17 выполняет присваивание справа налево, а более старые версии присваиваются слева направо? Другими словами, вы говорите, что C ++ 17 обратно несовместим в отношении порядка оценки назначений со старыми версиями C ++?

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

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

@tlively Вы утверждаете, что C ++ 17 выполняет присваивание справа налево, а более старые версии присваиваются слева направо? Другими словами, вы говорите, что C ++ 17 обратно несовместим в отношении порядка оценки назначений со старыми версиями C ++?

Нет, в предыдущих версиях C ++ порядок оценки для простого оператора присваивания не был определен . Компиляторы могли оценивать подвыражения в любом порядке.

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

Как уже было сказано в этой ветке, мы часто вносим изменения и улучшения в WebAssembly. Вы можете увидеть текущие предложения в полете здесь . Мы внедрили и отправили предложения, такие как неприхотливые преобразования float-to-int и операции расширения подписи, которые добавляли недостающие инструкции, как вы предлагаете. Но мы не можем вернуться и изменить инструкции, которые уже были отправлены, потому что это нарушит работу существующих пользователей.

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

Это то, с чем придется иметь дело всем компиляторам WebAssembly, несмотря ни на что. Рассмотрим этот код:

a = foo();
b = bar();
use(a);
use(b);

Поскольку все вызовы функций могут иметь побочные эффекты, ни один из них не может быть переупорядочен по отношению к другим. Единственный способ скомпилировать это в WebAssembly - сохранить a где-нибудь помимо стека значений, возможно, в локальном.

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

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

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

@verbessern, это здорово, что вы увлечены тем, чтобы сделать Wasm настолько хорошим, насколько это возможно, но мы должны помнить, что это обсуждение касается технической проблемы с крошечным уголком дизайна спецификации. Пожалуйста, отдайте должное @tlively за то, что

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

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

  • Любой генератор, который проходит через граф потока данных / представление SSA (как это делает LLVM) на пути к Wasm, не будет заботиться о деталях того, как подключен порядок аргументов, потому что это будет обрабатываться общим способом во время опускание до стекового представления.
  • Что касается удобочитаемости, как я думаю, @titzer имел в
    (t.store (addr_calc) (value_calc))
    который визуально отражает
    addr_calc := value_calc
    на языке высокого уровня.

Совершенно очевидно, что нынешний дизайн имеет недостатки. Вопрос в том, лучше ли для языка

  1. ничего не делать и принять незначительный недостаток
  2. ввести swap
  3. ввести t.store_ с замененными аргументами

Я склоняюсь против (3), потому что нам придется делать то же самое для каждого будущего варианта store (например, если мы определим первоклассные воспоминания или объект heap GC). Я был бы доволен либо (1), либо (2). В идеальном мире, возможно, store было бы спроектировано иначе, но сейчас мы не можем сломать веб-совместимость.

Я никогда не понимал исключения операторов стека, таких как dupe и swap из Wasm, когда это виртуальный ISA. Стоимость их добавления очень низкая (я полагаю), и многие люди считают, что эти инструкции лучше формулируют некоторые алгоритмы. Почему бы просто не сделать их счастливыми, какой бы субъективной ни была польза?

Я никогда не понимал исключения операторов стека, таких как dupe и swap, из Wasm, когда это виртуальный ISA. Стоимость их добавления очень низкая (я полагаю), и многие люди считают, что эти инструкции лучше формулируют некоторые алгоритмы. Почему бы просто не сделать их счастливыми, какой бы субъективной ни была польза?

Поскольку эти операции можно имитировать с помощью локальных переменных, я думаю, было ощущение, что спецификация 1.0 должна быть как можно более минимальной. Локальные переменные в основном «бесплатны» (с точки зрения времени выполнения, а не размера кода), потому что они просто служат еще одним местоположением + набором чистых назначений для целей распределения регистров / SSA, поэтому скомпилированный код, вероятно, не менее эффективен.

Эта позиция становится несколько менее разумной по мере добавления большего количества типов (поскольку для каждого типа требуется отдельная «временная» локальная система), и особенно, если добавляется тип, который не имеет представления по умолчанию. Тем не менее, манипуляции со стеком swap и dup будут отнесены к let , который в настоящее время уточняется. Таким образом, главный аргумент для добавления одной из этих инструкций (учитывая, что let уже в пути) будет основан на экономии размера кода.

Эта проблема может быть хорошим примером, который мотивирует swap . Однако в качестве общего принципа проектирования мы стараемся сохранить ISA небольшими и минимизировать перекрытия. Поскольку WebAssembly должен (более или менее) гарантировать постоянную обратную совместимость, введение новой инструкции требует постоянных затрат. Вероятно, есть немного больше места для маневра при рассмотрении основных операций со стеком, таких как swap и dup , но нам все равно нужна некоторая практическая мотивация (особенно с учетом let , как указано выше) .

Стоимость их добавления очень низкая (я полагаю)

Некоторые детали того, как проверяется тип недостижимого кода, на самом деле затрудняют их добавление, потому что они вводят новые ограничения, которые должна решить программа проверки типов. @ conrad-watt дает хорошее объяснение здесь , которое, кстати, касается очень похожей проблемы с добавлением отсутствующих инструкций стековой машины.

многие люди считают, что эти инструкции лучше формулируют некоторые алгоритмы. Почему бы просто не сделать их счастливыми, какой бы субъективной ни была польза?

Потому что это требует реальных усилий многих команд. Быстрый расчет «за пределами конверта» позволяет оценить стоимость такого изменения в несколько десятков тысяч долларов рабочего времени инженера как минимум. Мы не собираемся тратить эти усилия без убедительных данных, показывающих его преимущества.

@tlively также полностью прав в том, что я даже не dup (хотя я надеюсь, что мы сможем их решить в ближайшее время!).

Точно @tlive : дело в интересах и инвестициях, а не в фактической спецификации веб-сборки. Не каждая компания, которая хочет компилировать и запускать веб-сборку, стоит миллиард долларов. Каждая часть ожидаемого комплексного анализа отбрасывает всех остальных игроков с поля.

Хорошо, пусть будет так, миру придется просто инвестировать в это, чтобы иметь возможность компилировать и запускать код веб-сборки так же хорошо, как и крупные игроки.

@verbessern эта проблема (которая касается компиляции, а не выполнения WebAssembly) не является хорошим примером вашей точки зрения. Преобразование SSA в представление стека - это не сложный анализ, это более или менее неизбежный шаг в реализации достойного компилятора, ориентированного на Wasm. Добавление дополнительных инструкций не снизит сложность реализации в этом случае. Вот почему аргумент размера кода был бы лучшим способом мотивировать необходимость изменений.

Кроме того, точка зрения @tlively о стоимости реализации даже тривиальных инструкций, похоже, подразумевает противоположное тому, что вы говорите. Опять же, swap - действительно простая инструкция. Вероятно, это правда, что его реализация в веб-движках будет стоить нетривиальное количество инженерных часов в крупных технологических компаниях, но этот факт только дает преимущества более гибким и независимым реализациям.

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

РЕДАКТИРОВАТЬ: в комментарий выше было внесено несколько изменений; Я отвечал на его первоначальную итерацию

@ conrad-watt Похоже, я перегружен задачами и начинаю писать неактуальные вещи, я позволю вам решить проблему в одиночку на некоторое время.

В любом случае, это не только проблема компиляции, но и проблема для среды выполнения - дорогостоящие среды выполнения переупорядочивают инструкции и удаляют локальные переменные, которые генерируются, чтобы преодолеть отсутствие явных инструкций. И тут доходит до слова «спуск» и серой зоны, чего следует ожидать, а чего нет.

Я действительно открыл эту проблему, потому что это «просто используйте локальный» для каждой нетривиальной инструкции по хранению в памяти, что делает его практически требованием среды выполнения для оптимизации локальных переменных, что будет стоить каждой среды выполнения сейчас и в будущем. Размер байта лично для меня совершенно неактуален. Если размер байта был задан в веб-сборке, инструкции нужно было просто закодировать кодами переменной длины.

Также существует проблема, когда каждая новая стандартизированная инструкция только увеличивает нагрузку на реализацию каждой будущей реализации wasm. Производители wasm могут выбирать подмножество, которое лучше всего соответствует их модели компиляции, но потребителям необходимо будет реализовать 100% спецификации, иначе они потеряют любые надежды на совместимость. Добавление новых инструкций - это незначительные затраты для всех, у кого уже есть реализация, но добавляет к работе, необходимой новым игрокам.

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


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

Мне любопытно, какова ваша ментальная модель. Насколько я понимаю, все существующие движки обрабатывают как локальные, так и значения стека одинаково, как виртуальные регистры, которые затем реифицируются посредством распределения регистров. Что не кажется мне слишком сложным. Я чувствую, что есть определенный минимальный уровень сложности, который может принять wasm-движок, просто в силу проблемной области.

Мне любопытно, какова ваша ментальная модель. Насколько я понимаю, все существующие движки обрабатывают как локальные, так и значения стека одинаково, как виртуальные регистры, которые затем реифицируются посредством распределения регистров. Что не кажется мне слишком сложным. Я чувствую, что есть определенный минимальный уровень сложности, который может принять wasm-движок, просто в силу проблемной области.

Примерно так. Локальные переменные на самом деле являются просто ограничениями распределения регистров - они обычно не переводятся в фактические вычисления. Даже компилятор Chromium Liftoff, который является однопроходным и не выполняет никаких промежуточных этапов оптимизации, избегает генерации любого кода для local.get/set ( ссылка ). В самом худшем случае полностью наивному компилятору, возможно, придется безоговорочно mov их начальные значения и пролить дополнительный регистр или два, но это решается базовыми стратегиями распределения регистров.

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

Спасибо всем причастным.

Усилия, которые я потратил на объяснение проблемы, уже превзошли усилия, которые мне пришлось бы приложить, чтобы фактически реализовать многие из задействованных алгоритмов.

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

Это, в общем, ответ на вопрос «почему бы тебе просто не сделать одну простую вещь?» потому что на самом деле в этом пространстве нет ничего простого, и потому, что люди предпочли бы потратить усилия на более эффективную работу.

Я говорю это не для того, чтобы пренебречь или сказать, что для участия нужно быть готовым потратить все эти усилия в одиночку. Я говорю это для того, чтобы мы могли вспомнить уровень усилий, которые все участники wasm уже потратили и тратят на данный момент, особенно когда просят людей изменить свои приоритеты, чтобы сосредоточиться на какой-либо конкретной проблеме.


Если подумать об этом подробнее, то добавление инструкций никогда не решает проблему наивных компиляторов wasm в целом.

Если мы допустили ошибку и наши инструкции по умолчанию трудно настроить для языков, это то, что мы можем исправить, добавив новые инструкции. (На самом деле это уже произошло с инструкциями без перехвата float-to-int). Но если что-то сложно реализовать для движков, отменить это невозможно.

Допустим, мы добавляем полный набор инструкций t.store_ . Тогда простые компиляторы все равно будут на крючке, чтобы реализовать старые инструкции store_ если они хотят быть совместимыми со спецификацией, и действительно, если они хотят запускать любые программы, скомпилированные языками, которые нацелены на непереносимую версию. Так что они на крючке, чтобы реализовать их _regardless_. Мы вернулись к тому месту, с которого начали, где им приходится выбирать между более сложным анализом или наивными вещами с неоптимальной производительностью, поэтому все, что привело к добавлению альтернативных инструкций, - это увеличило общие усилия по реализации.

Это говорит о том, что мы должны категорически отвергать предложения о добавлении новых инструкций ради удобства wasm _engine_. Возможно, это все же стоит сделать, если это облегчит языкам нацеливание на wasm за счет возможности выбора из более широкого набора инструкций, но движки не могут выбирать и выбирать подмножество, поэтому дополнительные инструкции никогда не облегчают их работу.

(Еще есть что сказать о добавлении новых инструкций по соображениям производительности. Однако там стандарт намного выше; нам нужны как движки, так и множество языков, чтобы иметь возможность использовать преимущества новых инструкций, чтобы увидеть какие-либо реальные преимущества , поэтому вопросы: «Предотвращают ли существующие инструкции оптимизацию?», а также «достаточно ли это убедительно, чтобы языковые реализации действительно были нацелены на новые инструкции?»)

Стоимость их добавления очень низкая (я полагаю)

Я исправился. Хорошие баллы со всех сторон. Нужно заглянуть в let ...

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

С другой стороны, текстовый формат пытается быть удобным языком для разработчиков, создающих модули Wasm.

Я категорически не согласен с этим: P. У меня всегда было ощущение, что большинству разработчиков не нужно писать .wat вручную, и на самом деле он не был оптимизирован для этого варианта использования в общем смысле программирования. Насколько мне известно, люди, работающие над предложениями по спецификациям wasm, и некоторые авторы компиляторов являются двумя основными аудиториями текстового формата.

и некоторые полезные и удобные функции имеют смысл в этом контексте, но никогда не могут быть добавлены, кроме как через движок.

Это не совсем так; мы могли специфицировать только текстовые инструкции без особых затрат на обратную совместимость со средой выполнения, потому что механизмы wasm (о которых я знаю) используют только двоичный формат. Однако, поскольку поддержание этого соответствия 1: 1 с базовым двоичным файлом чрезвычайно важно для чтения дизассемблера и предложения новых функций, маловероятно, что мы будем стандартизировать много дополнительного сахара. ( Предложение аннотаций, вероятно, самое близкое к сахару, о котором мы думали добавить?)

Подход, который мне кажется наиболее плодотворным, - это создание языка, являющегося второстепенным расширением для .wat, и его использование. Уолт является здесь довольно хорошим примером , а также выводом wasm-decompile wabt (хотя это не тот язык, на котором вы можете писать ) относительно того, как далеко вы можете зайти в этом направлении.

Подход, который мне кажется наиболее плодотворным, - это создание языка, являющегося второстепенным расширением для .wat, и его использование. Уолт является здесь довольно хорошим примером, а также выводом wasm-decompile wabt (хотя это не тот язык, на котором вы можете писать) относительно того, как далеко вы можете зайти в этом направлении.

Я никогда не видел формата wabt wasm-decompile . На первый взгляд очень интересно. Спасибо.

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

У меня всегда было ощущение, что большинству разработчиков не нужно писать .wat вручную, и на самом деле он не был оптимизирован для этого варианта использования в общем смысле программирования. Насколько мне известно, люди, работающие над предложениями по спецификациям wasm, и некоторые авторы компиляторов являются двумя основными аудиториями текстового формата.

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

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

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

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

Artur-A picture Artur-A  ·  3Комментарии

JimmyVV picture JimmyVV  ·  4Комментарии

void4 picture void4  ·  5Комментарии

chicoxyzzy picture chicoxyzzy  ·  5Комментарии

arunetm picture arunetm  ·  7Комментарии