Сколько asm-инструкций на C-инструкцию?

Я понимаю, что на этот вопрос невозможно ответить абсолютно, но я только после цифр:

Учитывая разумную размерную C-программу (тысячи строк кода), в среднем, сколько ASM-команд будет сгенерировано. Другими словами, какое реалистичное соотношение между командами C-ASM? Не стесняйтесь делать предположения, например "с текущими архитектурами x86".

Я попробовал Google об этом, но ничего не нашел.

Добавление: заметив, насколько путают этот вопрос, я чувствую некоторую потребность в объяснении. То, что я хотел знать по этому ответу, заключается в том, чтобы на практике понять, что означает "3GHz", Я полностью осознаю, что пропускная способность per Herz сильно варьируется в зависимости от архитектуры, вашего оборудования, кэшей, скорости шины и положения луны.

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

Это не тривиальный ответ на место (как я заметил), и это было моим лучшим усилием в этом. Я знаю, что количество результирующих линий ASM на строки C зависит от того, что вы делаете. i++ находится не в той же окрестности, что и sqrt(23.1) - я знаю это. Кроме того, независимо от того, какой ASM я выхожу из C, ASM интерпретируется в различные наборы микрокода в процессоре, что опять же зависит от того, используете ли вы AMD, Intel или что-то еще и их соответствующие поколения. Я также знаю об этом.

Ответы на шары, которые я получил до сих пор, - это то, за чем я был: проект достаточно большой, примерно в 2 строках x86 ASM на 1 строку ANSI-C. Сегодня процессоры, вероятно, будут усредняться примерно на одной команде ASM за такт, как только конвейеры будут заполнены, и дадут достаточно большой выбор.

Ответ 1

Я не уверен, что вы подразумеваете под "C-инструкцией", может быть, постановкой или строкой? Конечно, это будет сильно отличаться из-за ряда факторов, но, посмотрев несколько моих собственных пробных программ, многие из них близки к отметке 2-1 (2 инструкции по сборке на LOC), я не знаю, что это означает или как это может быть полезно.

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

Edit

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

В то время как современный процессор может работать со скоростью 3 миллиарда циклов в секунду, что не означает, что он может выполнять 3 миллиарда инструкций в секунду. Вот несколько вещей, которые следует учитывать:

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

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

Ответ 2

Невозможно ответить. операторам int a; могут потребоваться нулевые строки asm. в то время как для инструкций типа a = call_is_inlined(); могут потребоваться 20 + asm-строк.

Вы можете увидеть себя, скомпилировав программу c, а затем запустив objdump -Sd ./a.out. Он будет отображать asm и C-код, смешанный, так что вы можете увидеть, сколько строк asm сгенерировано для одной линии C. Пример:

test.c

int get_int(int c);
int main(void) {
    int a = 1, b = 2;
    return getCode(a) + b;
}

$gcc -c -g test.c

$objdump -Sd ./test.o

00000000 <main>:
int get_int(int c);
int main(void) { /* here, the prologue creates the frame for main */
   0:   8d 4c 24 04             lea    0x4(%esp),%ecx
   4:   83 e4 f0                and    $0xfffffff0,%esp
   7:   ff 71 fc                pushl  -0x4(%ecx)
   a:   55                      push   %ebp
   b:   89 e5                   mov    %esp,%ebp
   d:   51                      push   %ecx
   e:   83 ec 14                sub    $0x14,%esp
    int a = 1, b = 2; /* setting up space for locals */
  11:   c7 45 f4 01 00 00 00    movl   $0x1,-0xc(%ebp)
  18:   c7 45 f8 02 00 00 00    movl   $0x2,-0x8(%ebp)
    return getCode(a) + b;
  1f:   8b 45 f4                mov    -0xc(%ebp),%eax
  22:   89 04 24                mov    %eax,(%esp)
  25:   e8 fc ff ff ff          call   26 <main+0x26>
  2a:   03 45 f8                add    -0x8(%ebp),%eax
} /* the epilogue runs, returning to the previous frame */
  2d:   83 c4 14                add    $0x14,%esp
  30:   59                      pop    %ecx
  31:   5d                      pop    %ebp
  32:   8d 61 fc                lea    -0x4(%ecx),%esp
  35:   c3                      ret

Ответ 3

Это сильно меняется! Я не верю никому, если они попытаются предложить грубое обращение.

Заявления типа i++; могут перевести на один INC AX.

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

Затем добавьте оптимизацию компилятора, которая будет собирать ваш код не таким, как вы его написали, тем самым устраняя инструкции.

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

Ответ 4

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

Вы просто перенастроены, и вы отбрасываете кеширование и т.д., как если бы оно было вторичным, тогда как оно вполне может быть полностью доминирующим.

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

Ответ 5

В зависимости от вашей среды вы можете использовать опцию visual studio:/FA

more здесь

Ответ 6

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

Что я буду делать: возьмите разумную программу размера C. Дайте gcc вариант "-S" и проверьте себя. Он будет генерировать исходный код ассемблера, и вы можете сами рассчитать соотношение для этой программы.

Ответ 7

RISC или CISC? Какая инструкция на C, во всяком случае?

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

Вы можете попытаться проанализировать академическую литературу по оптимизации сборки и перекрестному взаимодействию оборудования/программного обеспечения, которое произошло за последние 30-40 лет. То, где вы собираетесь найти какие-то реальные данные о том, что вас интересует. (Хотя я предупреждаю вас, вы можете увидеть данные C- > PDP вместо данных C- > IA-32).

Ответ 8

В одном из комментариев вы написали, что хотите знать, что означает 3GHz.

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