![]() |
C\C++
Давно на булке не было хорошего срача по поводу двух родственных языков. Пора его начать.
Уже как месяц, в перерывах между рисованием моделек и карт для своей игры, пишу говношутер на чистом си. Что могу по этому поводу сказать: 1) Почувствовал себя полным нубом в программировании когда у меня отняли stl с его std::vector и std::map. Пришлось писать свои велики, проходя по граблям снова и снова. 2) Компиляция просто офигенно быстрая, сейчас проект размером 250 кб кода компилируется mingw за 5 сек, для сравнения при смене компилятора на g++( то есть си++ компилятор ) тот же проект компилируется за 23 секунды. 3) Размер кода тоже меньше раза в 3 (тут скорее линкуется рантайм c++ в экзешник, поэтому такая разница) 4) Производительность практически одинаковая( разница 1-3%) при тех же ключах оптимизатора. Но производительность неоптимизированных версий различается на 10-15%. Причем си обходит си++. 5) Так как некоторые куски кода я брал из движка своей игры, то при портировании их на си, удалось серьезно их оптимизировать. 6) Наследование сменилось композицией, в некоторых местах оно даже удобнее наследования. 7) При программинге на си стал больше уделять внимания структуре игры\движка. В итоге не могу сказать что си прям очень сильно понравился, но он избавляет от гемора с наследованием и прочей ООП мишурой. Кароче let the срач begins! |
Ответ: C\C++
Ну чот попытка совсем никакая.
Цитата:
|
Ответ: C\C++
Про С++ что-либо конкретное сказать сложно, так как язык очень разносторонний.
Я считаю тут дело не в языке, а в том как на нём программировать. С++ так устроен что подразумевает набор конкретных методик и подходов для конкретного проекта, и в случае игр или движков эти методики часто не совпадают с теми которые написаны в книгах по введению в С++. Однако у программиста может сложиться стереотип что программировать надо так как учили с детства (как в этих книгах). Хотя например в Data Oriented Design подходе вообще подвергается критике большинство ООП методик к программированию. При этом подходы DOD удачно ложатся как на С так и на С++. Только в случае С меньше выбора и программист возможно своими усилиями может прийти к тем же выводам самостоятельно. А вот например есть интересная концепция pure function, которая формально относится к функциональным языкам (не путать с процедурными) таким как Haskell, однако эту штуку можно воспроизвести на С/С++ (ключом компилятора или эксплуатировав правило не использовать глобальные переменные и делая метод static'ом). А ещё есть варианты как на С можно программировать ООП подходом. Так что можно сделать вывод что эти языки не являются строго процедурными в случае С или строго ООП в случае С++ -- они достаточно гибкие чтобы программировать используя множество разнообразных подходов и техник. Так что в случае с mr.DIMAS'ом мне кажется что С из-за своих некоторых ограничений просто дал задуматься о таких вещах, которые на С++ мы часто делаем по привычке. Однако теперь ничто не мешает код получившийся на С перенести на С++ и он останется таким же эффективным, потому что эффективность в данном случае обуславливается подходом, а не языком. Так что если спорить, то о том какие подходы программирования лучше использовать для создания игр/игровых движков, а язык уж как нибудь подстроится (или нет -- тогда просто выбираем другой язык). Кстати в книге Стива Макконела - Совершенный Код, упоминалось одно из основных правил программирования что программировать надо с использованием языка, а не на языке. Другими словами сначала представь (вне терминах языка) что нужно сделать, а затем выбирай подходящий язык способный это реализовать. Что касается меня то я планирую некоторые куски кода С++ попробовать переписать на С. Но это скорее эксперимент, чтобы удостовериться в некоторых деталях связанных с синтаксисом. В целом С++ более строгий язык по части типов и как следствие более надежный в этом плане. |
Ответ: C\C++
Еще сишечка заставляет вспоминать простые алгоритмы типа сортировки массивов\списков( вот только не надо напоминать про qsort ), что позволяет прокачать "скилл" перед собеседованием - у наших работодателей трешовые вопросы на собеседованиях, поэтому приходится такую ерунду вспоминать и задрачивать перед тестом.
Цитата:
Хотя у себя в говношутере использую следующий подход Код:
typedef struct entity_s { Цитата:
|
Ответ: C\C++
Цитата:
Цитата:
Цитата:
Ну например математическая библиотека вполне очевидное место которое можно попробовать написать на С. То есть такой же быстрый код можно написать и на С++ но С даст тоже самое с более простым синтаксисом, вот об этом я и говорю. Например если я на С++ хочу сделать POD структуры и функции для их работы, то мне нужно следовать некоторым правилам чтобы структура была POD (для надёжности добавить проверку через std::is_pod, делать методы static, добавлять noexcept для исключения проверок на перехваты (это кстати визуал студии не касается -- там исключения отличаются от стандарта) и прочие штуки, в то время как С по другому делать и не умеет, и всё что я напишу будет так как мне нужно без утяжеления синтаксиса. Поэтому как я сказал это эксперимент касается синтаксиса, читабельности кода, а не каких то методов синтеза более оптимального или быстрого бинарного кода, по идее он должен быть одинаковый, за исключением каких то деталей, зависящих от компиляторов. |
Ответ: C\C++
Цитата:
Код:
typedef struct { Код:
vec3_t a,b,c; |
Ответ: C\C++
Да есть выбор, либо пользуешься классами и перегрузкой операторов и получаешь мало буков, либо пишешь в си-стайл и в варианте на с++ получаешь даже более длинные тексты чем в си.
Кстати в твоём примере показана интересная особенность языка С -- из за отсутствия inline такие короткие функции могут стать причиной частых кеш-промахов и большого оверхеда на сам вызов функций. У себя в рейкастинге я в критических местах не пользовался даже готовыми матфункциями, а писал сразу хард-кодом целый блок вычислений. В целом в услвиях достаточно стабильного графического пайплайна рейкастинга не требуется частых переписываний, поэтому выбранный мной подход пока себя оправдывает. Причина почему в d3dx использовали такой подход я думаю кроется в том числе в намерении сделать библиотеки совместимые со множеством разных нативных языков. Не думаю что думать о таких вещах правильно когда цель gapi вычислять графику как можно быстрее. В dx11 они вроде сосредоточились исключительно на с++11 (из нативных языков, а так конечно вездесущий шарп там есть тоже). Вообще если вернуться к вопросу оптимизации то твоя структура не очень правильно написана: Код:
typedef struct entity_s { Ещё лучше делить такие большие структуры на "горячие" и "холодные" части. Предположим что первые три поля используются очень часто (каждый кадр или чаще), а другие реже, по мере трансформации объекта или запроса на изменение (ну тут ты сам лучше знаешь что и когда у тебя используется). Поэтому данные лучше распределить по двум структурам. Код:
// Первая: Код:
entityHot_t hotEntities[ number ]; Обход первого массива (hotEntities) займет гораздо меньше времени, потому что потребуется прокешировать гораздо меньше данных чем во втором случае. Возможно в языках с таким синтаксисом это не очень удобно, или же потребуется что-то придумать с макросами или обёртками. Но я видел более "заточенные" для игр языки где это решалось вот так: Код:
struct entity_t { |
Ответ: C\C++
Кстати, какие под Си есть макросы кроме cmacro?
|
Ответ: C\C++
Цитата:
http://www.greenend.org.uk/rjk/tech/inline.html Цитата:
|
Ответ: C\C++
Мне кажется, кое-кто не учитывает такой фактор, как время разработки. Да, можно писать офигенно быстрые штуки на Си, велосипедить списки, сортировки и прочее. Но нафига? Писать, сравнивать производительность, искать ошибки. Придётся расстаться либо с надёжностью, либо со временем, которое уйдёт на тестирование.
Цитата:
Но если алгоритм разрабатывать "на ходу", пробовать менять различные его части, сравнивать точность вычислений и прочее, то код вида a = b+c намного проще для изменений и поиска ошибок. Кстати, одна ошибка уже есть: в твоём примере c = b+c. Кроме того, не раскрыта тема высокоуровневых оптимизаций. В С++ или java я могу в несколько строчек заменить, например, реализацию списка с ArrayList на LinkedList и этим повлиять на производительность. Значительная часть потерь скорости зависит не от константы времени выполнения, а от ассимптотики - судя по моему опыту, возможность легко и быстро писать/изменять код даёт намного больший бонус, чем мелкие локальные оптимизации. Кроме того, всякие локальные оптимизации есть смысл использовать только в "бутылочном горлышке", в остальных случаях можно забить и не тратить своё время. |
Ответ: C\C++
Цитата:
Цитата:
|
Ответ: C\C++
Цитата:
P.S. Когда делал свою реализацию матриц, ради интереса написал к ней тесты - поймал несколько ошибок и ещё как минимум одну не поймал. |
Ответ: C\C++
Цитата:
Цитата:
И потом одна важная вещь: разработка кода это не весь процесс разработки, иногда в перспективе лучше один раз хорошо поработать над движком, на котором затем можно выпустить целую серию игр без больших проблем, что в целом сэкономит время. Цитата:
|
Ответ: C\C++
[fatmode=ON]
Смысл этого топика "Я хочу в 10 раз больше писать кода, который в 20 раз сложнее обслуживать ради 0.05% улучшения производительности" ? [/fatmode] |
Ответ: C\C++
ссылочка на хабр
Вот пример - ошибку в сортировке timsort нашли только тогда, когда попытались математически доказать корректность алгоритма. И то, нашли только сейчас, и некорректная реализация оказалась в Android SDK, Oracle JDK и OpenJDK. Принципы работы сортировок, списков, деревьев знать надо, но писать их самому "просто потому что могу" не стоит. |
Ответ: C\C++
Цитата:
Но смотри -- не надо путать две вещи: первая это когда ты знаешь логику алгоритма и используешь готовые отлаженные реализации зная что они работают так как тебе надо. Вторая это когда ты не знаешь как код работает, а только надеешься на то что он даст нужный тебе результат, это использовать так называемый чёрный ящик. Поэтому ты правильно говоришь что нужно использовать готовые решения и знать как они работают. Но большинство понимают так что нужно использовать готовое, а их правильность априори гарантирована. Если бы тот чел из статьи не знал как должен работать алгоритм сортировки, он бы не смог его исправить. Когда ты понимаешь суть работы алгоритма, твои ошибки могут быть в синтаксисе или каких-то опечатках, но они при пошаговой отладке легко находятся и исправляются. Ты контролируешь свой код. Если же ты не знаешь как работает код тебе гораздо сложнее понять почему у тебя программа работает неправильно. А если действительно ошибка в стандартной библиотеке, а пользователь ей на 100% доверяет? Я могу привести много примеров когда разработчики использовали чужие движки или софт в котором не разбирались и это приводило к большим проблемам когда баги возникали внутри этого софта. Если ты используешь чужой софт то его нужно изучить, порой это не легче чем написать свой, поэтому и выбор не такой однозначный. Ещё одно важное различие: одно дело придумать новый алгоритм, другое дело написать ручками, но всё же уже придуманный алгоритм. Когда я говорю что написал свою сортировку это значит только то что я взял известный алгоритм, просто адаптировал его под свои задачи, мне требовались изменения в коде, вот и всё. Так что не всё так просто: для каждой отдельной ситуации есть своё оптимальное решение. [doublefatmode=ON] Цитата:
[/doublefatmode] |
Часовой пояс GMT +4, время: 10:47. |
vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot