2013-04-06 4 views
2

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

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

Итак, вот несколько примеров ожидаемого поведения:

  1. На 8-битным микроконтроллером с шиной памяти 8-битном, я хочу это только нагрузка 1 байт, так как это займет многократные (медленные) операции памяти для загрузки, и теоретически для выполнения текущего кода операции может потребоваться только 1 байт.
  2. На 8086 (16-разрядном) я хотел бы загрузить 2 байта, потому что для загрузки только 1 байт мы в основном собираем некоторые полезные данные, чтобы их можно было прочитать позже, но я не хочу загружать более 2 байтов, потому что это потребует нескольких операций.
  3. В 32-битных ARM-процессах sor, я бы хотел загрузить 4 байта, потому что иначе мы либо бросаем данные, которые, возможно, придется снова читать, либо мы делаем несколько операций

Я бы сказал, что это можно легко обрабатывать просто предположив, что unsigned int достаточно хорош, но на 8-битных микроконтроллерах AVR int определяется как 16-разрядный, но ширина шины данных памяти составляет всего 8 бит, поэтому потребуется 2 операции загрузки памяти.

Во всяком случае, нынешние идеи:

с использованием uint_fast16_t, кажется, работает, как ожидалось на большинстве платформ (32 бита на ARM, 16 бит на 8086, 64 бита на x86-64). Тем не менее, он, очевидно, все еще не содержит AVR и другие 8-битные микроконтроллеры.

Я думал, что с помощью может работать, но он будет появляться на большинстве платформ, что она определяется как unsigned char, который, безусловно, не является оптимальным

Кроме того, есть еще одна проблема, которая должна быть решена, а также: выровненным памяти доступ. На x86 это, вероятно, не будет проблемой (теоретически он выполняет 2 операции с памятью, но, вероятно, кэшируется в аппаратном обеспечении), однако на ARM я знаю, что выполнение 32-битного доступа без выравнивания может стоить в 3 раза, как одна выровненная 32-разрядная нагрузка. Если адрес не выравнивается, я хочу загрузить выровненную опцию и получить как можно больше данных, но любой ценой избежать другой операции с памятью.

Есть ли способ как-то сделать это с использованием магического препроцессора или какого-либо такого или требуется ли просто вручную определять оптимальный размер кеша перед компиляцией для платформы?

+0

Ваша строительная процедура (например, ваш 'Makefile') может запускать некоторую команду настройки, например. сгенерируйте файл заголовка, содержащий соответствующий '# define' ... Но я не уверен, что ваша идея« кэширования »заставит вашу виртуальную машину работать быстрее ... –

+0

@BasileStarynkevitch Почему 4 дискретных памяти никогда бывают быстрее, чем одна дискретная нагрузка? Особенно, когда вы выбрасываете данные на уровне сборки. Также мне очень хотелось бы избежать использования любого кода, генерирующего свойства configure (мне нравится мой простой процесс сборки :)) – Earlz

+0

Поскольку компилятор может их оптимизировать, и потому, что, возможно, большая часть затрат на интерпретацию VM находится в другом месте ... Если вы не хотите создавать настраиваемые материалы, которые не могут решить вашу проблему ... Кроме того, ваша загрузка в 4 байта обычно не выравнивается и имеет значительную производительность. Вы пытаетесь выполнить микро-оптимизацию вручную, что почти всегда плохо (особенно если вы не сравнили его). Оставьте микро-оптимизации для компилятора. –

ответ

0

Нет автоматического способа сделать это с использованием типов или информации, предоставляемой стандартом C (в заголовках, например, и так далее).

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