Был бы какой-то смысл в разработке процессора, который мог бы обрабатывать IL напрямую? - PullRequest
12 голосов
/ 24 января 2009

Если я правильно понимаю:

Современные компании, разрабатывающие ЦП, такие как AMD и Intel, имеют свои собственные коды API (язык ассемблера), которые они считают языком 2G поверх машинного кода (язык 1G)

Было бы возможно или желательно (производительность или нет) иметь процессор, который будет выполнять обработку IL на своем ядре вместо текущих вызовов API?

Ответы [ 5 ]

24 голосов
/ 24 января 2009

Аналогичная технология существует для Java - ARM делает ряд процессоров, которые могут сделать это, они называют это своей технологией "Jazelle".

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

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

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

15 голосов
/ 24 января 2009

Вы, кажется, немного смущены тем, как работает процессор. Сборка не является отдельным языком от машинного кода. Это просто другое (текстовое) представление.

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

Если я пишу add $10, $9, $8 и запускаю его через ассемблер, я получаю машинный код для инструкции добавления, получая значения в регистрах 9 и 8, добавляя их и сохраняя результат в регистре 10.

Между ассемблером и машинным кодом существует соотношение 1: 1.

Также нет "вызовов API". Процессор просто читает с адреса X и сопоставляет последующие биты со всеми инструкциями, которые он понимает. Как только он находит инструкцию, которая соответствует этому битовому шаблону, он выполняет инструкцию и переходит к чтению следующей.

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

Таким образом, возникает вопрос: «Является ли ваш IL-код лучшим, более эффективным представлением программы, чем машинный код, который сейчас поддерживает ЦП?»

И ответ, скорее всего, нет. MSIL (я полагаю, это то, что вы имеете в виду под ИЛ, что является гораздо более общим термином) разработан так, чтобы быть переносимым, простым и последовательным. Каждый язык .NET компилируется в MSIL, и каждая программа MSIL должна быть в состоянии перевести в машинный код для любого процессора в любом месте. Это означает, что MSIL должен быть общим и абстрактным, а не делать предположения о процессоре. По этой причине, насколько мне известно, это чисто стековая архитектура. Вместо хранения данных в регистрах каждая инструкция обрабатывает данные в верхней части стека. Это хорошая, чистая и универсальная система, но она не очень эффективна и плохо отражается на жесткой структуре процессора. (В вашем замечательном маленьком мире высокого уровня вы можете притворяться, что стек может свободно расти. Чтобы центральный процессор мог получить к нему быстрый доступ, он должен храниться в некоторой небольшой быстрой встроенной памяти с конечным размером. Итак, что происходит если ваша программа помещает слишком много данных в стек?)

Да, вы могли бы сделать ЦП для непосредственного выполнения MSIL, но что бы вы получили? Вам больше не нужно JIT-код перед выполнением, поэтому при первом запуске программы она запускается немного быстрее. Кроме этого, хотя? После того как ваша MSIL-программа была обработана JIT, она была переведена в машинный код и работает так же эффективно, как если бы она была изначально написана в машинном коде. Байт-код MSIL больше не существует, это просто последовательность инструкций, понятная ЦП.

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

12 голосов
/ 24 января 2009

Это не новая идея - то же самое было предсказано для Java, и машины Lisp даже были фактически реализованы.

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

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

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

6 голосов
/ 24 января 2009

Я бы сказал нет.

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

Поэтому, чтобы машина распознала IL напрямую, просто перенесли бы всю логику компиляции JIT из программного обеспечения в аппаратное обеспечение.

Это сделало бы весь процесс очень жестким и неизменным.

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

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

0 голосов
/ 24 января 2009

Я бы так не думал по двум причинам: -

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