Сделать скомпилированный бинарный файл на родной скорости без нареканий без перекомпиляции из исходного кода в другой системе? - PullRequest
3 голосов
/ 09 января 2011

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

Обычно, когда мы хотим, чтобы наша программа работала с собственной скоростью в системе, будь то Windows, Mac OS X или Linux, нам нужно скомпилироватьиз исходников.Если вы хотите запустить программу другой системы в вашей системе, вам нужно использовать виртуальную машину или эмулятор.Несмотря на то, что эти инструменты позволяют вам использовать нужную программу на неродных ОС, у них иногда возникают проблемы с производительностью и глюками.

У нас также есть более новый компилятор под названием «JIT Compiler», где компилятор будет анализировать программу байт-кода на родном машинном языке перед выполнением.Производительность может очень сильно увеличиться с JIT Compiler, но производительность все равно не такая, как при работе на собственной системе.

Другая программа для Linux, WINE, также является хорошим инструментом для запуска Windows.программа в системе Linux.Я попытался запустить Team Fortress 2 и поэкспериментировать с некоторыми настройками.Я получил ~ 40 к / с в Windows при среднем значении 1280 x 1024. В Linux мне нужно снизить все до 1280 x 1024, чтобы получить ~ 40 к / с.Однако есть две примечательные вещи:

  1. Настройки модели полигона не влияют на частоту кадров, независимо от того, установлен ли я на низком или высоком уровне.
  2. При наличии эффектов постобработки или некоторых специальных эффектовкоторые требуют манипуляции с нарисованными пикселями текущего кадра, частота кадров упадет до 10-20 кадров в секунду.

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

В любом случае, этот вопрос довольно теоретический.Есть ли что-нибудь, что мы можем сделать вообще?Я вижу, что WINE может запускать STEAM и Team Fortress 2. Хотя есть недостатки, они могут работать при более низких настройках.Или, возможно, я должен также спросить: « возможно ли перевести одну целую программу в системе в другую систему без перекомпиляции из исходного кода и получить собственную скорость? » Я вижу, что у нас также есть компилятор AOT, не так лиМожно ли использовать его для чего-то вроде этого?Или существует так много ограничений (таких как вызов DirectX или различия в архитектуре программного обеспечения), которые делают невозможной безупречную и не встроенную в системную программу, которая работает с собственной скоростью?

Ответы [ 2 ]

6 голосов
/ 09 января 2011

Первый шаг к запуску одного и того же скомпилированного тела кода на нескольких системах на собственной скорости без перекомпиляции - это выбрать один набор инструкций процессора и выбросить все другие системы.Если вы выбираете Intel, то вы должны выбросить ARM, MIPS, PowerPC и т. Д., Поскольку инструкции по машинному коду для одной архитектуры совершенно непонятны другим процессорам.

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

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

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

Формат исполняемых файлов MSDOS .com делает это как минимум с 1981 года, а CP / M задолго до этого.

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

Поскольку каждая ОС имеет свой собственный формат исполняемых файлов, вам также необходимо выяснить, как поместить свой блок «безупречного» нативного кода в память на всехэти разные операционные системы.Вам понадобится как минимум один загрузчик программ, скомпилированный для каждой операционной системы, в которой вы хотите запустить свой блок нативного кода. Пока вы пишете загрузчик программ для каждой ОС, на которую вы хотите ориентироваться, вы также можете определить свой собственный файл I /O функции, которые отображаются на собственные эквиваленты ОС, так что ваш блок собственного кода может выполнять файловый ввод / вывод в любой системе.То же самое для консольного ввода-вывода или графического вывода.

Ой, подождите - это именно то, что делает WINE.

Именно поэтому частоты кадров, которые вы видите в WINE, намного ниже, чем те же операции в хост-ОС - WINE переводит графические вызовы Win32 GDI в нечто, предоставляемое собственной хост-ОС (Linux -> XWindows)и там, где нет точного соответствия функции или если есть семантическое несоответствие операции (что часто имеет место), WINE должен реализовать всю функциональность самостоятельно, иногда с большими затратами.

Но учитываяПовсеместное использование стандартизированного оборудования, такого как диски IDE, USB-устройства и функции BIOS, может быть, вам не нужно тратить время на сопоставление собственных переносимых API-интерфейсов с тем, что встроено в ОС. Просто напишите небольшой код для файла I/ O для IDE-устройств, выводить графики с использованием функций VESA BIOS.Если вы немного абстрагируете код, вы можете поддерживать несколько видов оборудования и выбирать соответствующий указатель функции для использования в зависимости от того, какое оборудование вы найдете во время выполнения.

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

Ой, подождите - вы только что написали свою собственную ОС.;>

4 голосов
/ 09 января 2011

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

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

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

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

Время рассказа. Корпорация Digital Equipment Corporation создала систему под названием FX! 32, которая взяла собственные скомпилированные исполняемые файлы Win32 Intel x86, декомпилировала их и преобразовала логику в собственные инструкции процессора Alpha AXP под управлением Windows NT AXP.В этом случае операционные системы были, по крайней мере, вырезаны из одной и той же ткани, но одна была 32-битной, а другая 64-битной, и на уровне машинного кода у них были радикально разные соглашения о вызовах.Тем не менее, это работало, и это работало замечательно хорошо.Из-за различий в оборудовании приложение Intel x86, работающее на AXP, может в конечном итоге работать быстрее, чем то же приложение, работающее на оборудовании Intel.(FX! 32 использовал профилирование для повторной оптимизации кода AXP после того, как приложение Intel запускалось несколько раз, поэтому производительность обычно начиналась довольно плохо, но улучшалась при каждом запуске приложения)

Однако, хотя все выполнялосьСобственные инструкции AXP, переведенное приложение FX! 32 никогда не работало так быстро, как при взятии исходного кода и его перекомпиляции специально для набора команд AXP.Переведенный в FX! 32 собственный поток команд AXP был увеличен из-за необходимости полного представления семантики исходных инструкций Intel x86, даже если (невидимый) алгоритм более высокого уровня не требовал всех аспектов этой семантики.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...