2015-04-04 7 views
2

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

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

Я написал два тестовых файла для вычисления простой арифметической задачи.

// test1.c 
int main(int argc, char* argv[]){ 
    int x = 4243; 
    int y = 3235; 
    int z = 613*x + 725*y; 
    return 0; 
} 

// test2.c 
int main(int argc, char* argv[]){ 
    int x = 4243; 
    int y = 3235; 
    int z = (((((((x << 3) + x) << 1) + x) << 3) + x) << 2) + x + 
     (((((((((y << 2) + y) << 1) + y) << 2) + y) << 2) + y) << 2) + y; 
    return 0; 
} 

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

Теперь, если я компилирую с флагом ССАГПЗ -S, машинный код является 31 линии для test1.s и 47 линий с test2.s

Каковы возможные объяснения? Предполагается ли, что меньшее количество строк машинного кода означает более быстрое выполнение ошибок? Используется ли файл .s для чего-либо до создания двоичного файла? Является ли моя игрушка фиктивной?

Спасибо за любые идеи

+3

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

+2

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

+2

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

ответ

2

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

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

Но в настоящее время ничего подобного не существует. У вашего (предположительно современного) процессора, безусловно, есть встроенная команда умножения, которая номинально выполняется в очень маленьком числе тактовых циклов (small, as in, 3), поэтому использование ее будет работать быстрее (и быть меньше), чем разбить умножение на несколько смен операций, каждый из которых номинально исполняется за один такт.

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

Итак, коротко отредактируйте короткую историю: «научитесь прекращать волноваться и любить бомба».

+0

Ну, наверное, не один * цикл .. но не много. – harold

+0

@harold, вы правы, я посмотрел его, и получается, что * latency * для целочисленного умножения на intel i7 в настоящее время составляет 3 такта. Я исправил свой ответ. –

+0

Задержка обучения не имеет никакого отношения к времени, которое необходимо выполнить. На любом современном процессоре целочисленное умножение составляет 1 каждый цикл. И вы можете делать 4 или 8 раз в каждом цикле с SIMD-расширениями. – ElderBug

0

Если вы пишете для процессора, который не имеет инструкции умножения (такие процессоры существуют), и если вам нужно много раз вычислять 613*x + 725*y, тогда, возможно, стоит написать собственный бит-сдвигающий код.

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

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

  • Нет связанных вопросов^_^