Действительно ли C неэффективен по сравнению с блоком? [дубликат]

7
задан Community 23 May 2017 в 12:33
поделиться

11 ответов

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

15
ответ дан 6 December 2019 в 04:47
поделиться

C не является неэффективным по сравнению ни с чем. C - это язык, и мы не описываем языки с точки зрения эффективности. Сравним программы по эффективности. C не пишет программ; программисты пишут программы.

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

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

13
ответ дан 6 December 2019 в 04:47
поделиться

Если вы не являетесь экспертом по ассемблеру и (или) не используете преимущества продвинутых опкодов, не используемых компилятором, компилятор C, скорее всего, победит.

Попробуйте ради интереса ;-)

Более реалистичные решения часто заключаются в том, чтобы позволить компилятору Си сделать свою часть работы, а затем профилировать и, если нужно, подправить определенные секции - многие компиляторы могут выгрузить что-то вроде низкоуровневого IL (или даже "ассемблера").

4
ответ дан 6 December 2019 в 04:47
поделиться

Это зависит от обстоятельств. Компиляторы C для Intel в настоящее время неплохо справляются со своей задачей. Меня не так впечатлили компиляторы для ARM - я мог легко написать ассемблерную версию внутреннего цикла, которая выполнялась вдвое быстрее. Обычно сборка на машинах x86 не требуется. Если вы хотите получить прямой доступ к инструкциям SSE, изучите встроенные функции компилятора!

3
ответ дан 6 December 2019 в 04:47
поделиться

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

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

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

2
ответ дан 6 December 2019 в 04:47
поделиться

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

Эта сумма зависит от того, как вы определяете «современный компилятор Си». Совершенно новый компилятор (для чипа, который только что вышел на рынок) может иметь большое количество недостатков, которые со временем будут устранены. Просто скомпилируйте несколько простых программ (например, функции string.h) и проанализируйте, что делает каждая строка кода. Вы можете быть удивлены некоторыми расточительными вещами, которые делает непроверенный компилятор C, и распознаете ошибку, просто прочитав код. Зрелый, хорошо протестированный, тщательно оптимизированный компилятор (Think x86) отлично справится с созданием сборки, хотя новый по-прежнему будет выполнять достойную работу.

Ни в коем случае C не может справиться лучше, чем сборка. Вы можете просто протестировать эти два теста, а если ваша сборка была медленнее, скомпилируйте с -S и отправьте получившуюся сборку, и вам гарантирована ничья. C скомпилирован в сборку, которая имеет соотношение 1: 1 с байт-кодом. Компьютер не может делать то, что не может сделать сборка, при условии, что опубликован полный набор инструкций.

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

Компилятор не может определить «производительность», как человек. Я понимаю, что вы сказали тривиальные программы, но даже в самых простых (полезных) алгоритмах будет компромисс между размером и скоростью. Компилятор не может сделать это в более мелком масштабе, чем флаги -Os / -O [1-3], но человек может знать, что «лучший» означает в контексте цели программы.

Некоторые архитектурно-зависимые инструкции сборки не могут быть выражены на C. Вот здесь-то и появляются операторы ASM (). Иногда они вообще не предназначены для оптимизации, а просто потому, что нет способа выразить в C, что эта строка должна использовать, скажем, атомарную операцию test-and-set, или что мы хотим вызвать прерывание SVC с закодированным параметром X.

Несмотря на вышесказанное, C на несколько порядков более эффективен для программирования в и освоить. Если производительность важна, потребуется анализ сборки и, вероятно, будут найдены оптимизации, но затраты времени и усилий разработчика на сложные программы на ПК редко окупаются. Для очень простых программ, которые должны быть максимально быстрыми (например, RTOS) или которые имеют серьезные ограничения памяти (например, ATTiny с 1 КБ флэш-памяти (без возможности записи) и 64 байтами ОЗУ), сборка может быть единственным способом. идти.

2
ответ дан 6 December 2019 в 04:47
поделиться

Это зависит от компилятора, который вы используете? Это не свойство C или любого другого языка. Теоретически возможно загрузить компилятор таким сложным ИИ, что вы сможете скомпилировать prolog на более эффективный машинный язык, чем GCC может сделать с C.

Это зависит на 100% от компилятора и на 0% от C.

Что имеет значение, так это то, что C написан как язык, для которого легко написать оптимизирующий компилятор из C -> ассемблер, а под ассемблером подразумеваются инструкции машины фон Неймана. Это зависит от цели, некоторые языки, такие как prolog, вероятно, будет легче отобразить на гипотетические "редукционные машины".

Но, учитывая, что ассемблер является целевым языком для вашего компилятора Си (технически вы можете компилировать Си в brainfuck или в Haskell, теоретической разницы нет), то:

  • Можно написать оптимально быструю программу на этом самом ассемблере (duh)
  • Можно написать компилятор Си, который в каждый момент времени будет производить наиболее оптимальный ассемблер. То есть, существует функция от каждой программы на Си до наиболее оптимального способа получить тот же ввод/вывод на ассемблере, и эта функция вычислима, хотя, возможно, и не детерминистически.
  • Это также возможно для любого другого языка программирования в мире.
0
ответ дан 6 December 2019 в 04:47
поделиться

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

Продолжая ... знания C и Assembly абсолютно недостаточно для выполнения работы лучше, чем компилятор в 99,99% случаев, и считал, что программирование чего-либо на C может быть В 10000 раз быстрее, чем программирование той же ассемблерной программы, лучший способ потратить некоторое время - оптимизировать то, что компилятор сделал неправильно в оставшихся 0,01%, а не изобретать колесо.

1
ответ дан 6 December 2019 в 04:47
поделиться

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

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

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

9
ответ дан 6 December 2019 в 04:47
поделиться

Используйте C для большинства задач и напишите встроенный ассемблерный код для конкретных (например, чтобы воспользоваться преимуществами SSE, MME, ...)

5
ответ дан 6 December 2019 в 04:47
поделиться

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

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

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

3
ответ дан 6 December 2019 в 04:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: