Комментарии 90
Magic numbers и сырые строки, конечно удручают.
А так, всё как у людей.
Думаю, надо просто убрать эту функцию и все будет ок. Пусть разработчик пишет свою реализацию на основе модели проца и числа ядер.
Завтра big.LITTLE может появиться и в windows, в любом случае планировщику приложения надо понимать, что не все ядра имеют одинаковую производительность.
Зачем этот костыль в десктопах?
Десктопам не нужна автономность.
Windows уже поддерживает big.LITTLE/DynamIQ для ARM и аналогичную схему для x86-64.
В этом году вышли первые гибридные Intel процессоры Lakefield, и можно даже купить девайсы с ними (Samsung Galaxy Book S).
По-идее это уже существует в Ryzen 3xxx (видимо, и более новых). Процессор каким-то образом калибруется, в нем определяется самое производительное ядро, а также самые производительные ядра в чиплете (CCX). И эта информация может сообщаться ОС, и Windows умеет использовать информацию для планирования scheduling'а.
Скрин из Ryzen-master в котором отмечены эти ядра
Это скорее балансирование каналов памяти в режимах с 2, 4, 8 активными ядрами.
Но может и стабильность работы на пиковых частотах как-то тоже прошивается в них, не уверен.
UPD: Всё ещё сложнее. Они и оверклокинг, и каналы памяти, и общие кэши, и даже близость учитывают в выборе "любимых" ядер.
Вот это особенно порадовало: "CPPC2 deliberately misreports "favored cores" to the Windows scheduler — to build core rotation pairs within localized groups of cores, rather than picking cores from different CCXs or CCDs to build rotation pairs."
Но, в целом, это не то же самое, что гетерогенные CPU.
Про magic numbers ещё можно дискутировать, но смысла в замене “AuthenticAMD” на какой-нибудь AMD_CPU_VENDOR_NAME я вижу ровно 0.
— 13 в «char vendor[13];» — «13 символов в название хватит всем», конечно же
— 0x15 в «0x15 == getCpuidFamily()» — ну да, все же помнят полную таблицу cpuid. а печально тут то, что прямо СРАЗУ после этого пришлось вставлять коммент о том, что же это за «0x15» вместо того, чтобы написать некий «CpuidEnum.Bulldozer == getCpuidFamily()» и получить самодокументирующийся код
Только непонятно почему "ошибка"? Это просто такое поведение по умолчанию. Для части задач подходит для части нет. С учётом того что библиотека "для одного приложения" то подход по умолчанию выглядит логичным.
if (0x15 == getCpuidFamily())
увидеть если процессор оказывается старше поколения Bulldozer? А я объясню как, достаточно просто не включая головы заниматься рерайтингом чужих статей и проигнорировать что в НЫНЕШНЕЙ версии библиотеки, с 2017 года, как раз исправленно, и код выше как раз проверяет на то что процессор обладает модулями, вместо полноценных ядер (процессоры серии fx и прочие bulldozer.). Вот вам коммит github.com/GPUOpen-LibrariesAndSDKs/cpu-core-counts/commit/49a6e7349dd3a73dfc4e85e5192b4c14215151dc
Тоесть смысл в том, что раздолбаи из CDPR воспользовались древней версией библиотеки, и вины ни амд, ни интела тут нет.
Функция вернет число 8 на бульдозере 4c/8t, и 6 на Ryzen 5 1600 с конфигурацией 6c/12t. Это не оптимально и сама АМД это пишет.
if (0x15 == getCpuidFamily()) {
// AMD "Bulldozer" family microarchitecture
count = logical;
}
else {
count = cores;
}
4 модуля у FX-8370 = 8 int + 4 float.
В маркетинговых целях процессоры на архитектуре Bulldozer позиционировались как процессоры с 8/6/4 ядрами. Однако, каждый процессор содержал указанное число лишь блоков целочисленных операций, количество блоков операций с плавающей запятой было вдвое меньше, отчего при большом количестве операций с плавающей запятой процессор показывал значительно меньшую производительность
У меня ryzen 5 1600, игра изначально задействует все 12 логических ядер. Я даже не всякий случай правил исполняемый файл игры, разницы замечено не было.
Смешно, но поиски, например, информации о том, что такое hyperthreading у Intel особо не дают толковой документации, особенно от самого Intel. Как не дают и ответа, как можно повысить производительностью, исполняя работу для двух ядер на одном.
Это было годами — технология как бы есть, ее продают как фичу более дорогих процов, а описания для желающих узнать — как бы и нет. И только слухи на форумах, под какие задачи лучше включать HT, а под какие выключать.
Здесь (в оригинале, конечно) призывается масштабировать ПО на число логических ядер. Те автор верит, чтт лигияеское не худе, чем физическое. Значит ли это, что 2 ядерный процессор вдруг стал 4-ядерным? Очевидно, нет, и все как-то сложнее.
Что дает тот же вывод, чтт и в приведенной автором статье — тестируйте!
Грубо говоря, ядро может выполнять разные типы задач. Допустим, сложение целых чисел и сложение чисел с плавающей запятой. В обычной ситуации эти задачи будут выполняться по очереди. То есть, один из блоков будет простаивать. Логично попробовать загрузить ядро по полной и дать ему обе задачи одновременно. Но подходит такое не для каждого алгоритма. Допустим, в программе нет вычислений с плавающей запятой. Тогда ускорение получить не выйдет.
Как не дают и ответа, как можно повысить производительностью, исполняя работу для двух ядер на одном.Принцип работы hyperthreading становится гораздо более очевидным, если вспомнить, что одно «ядро» состоит из нескольких разнородных вычислительных блоков, обычно загруженных весьма неравномерно, а тот самый hyperthreading — это по сути просто два конвейера с инструкциями к нему. Таким образом одновременное выполнение двух потоков повышает утилизацию вычислительных блоков одного ядра.
Яблочный М1, кстати, делает это еще агрессивнее: в архитектуре ARM можно иметь SMT сразу в 4 потока. Причем потенциал больше, чем в х86 за счет более простого декодера коменд (из-за однородности их размера).
Причем потенциал больше, чем в х86 за счет более простого декодера коменд (из-за однородности их размера).А простота декодера из-за однородности размера команд вполне компенсируется сниженной эффективностью такого кода, требующего большего количества инструкций.
Конкретно M1 этого не делает. Там нет SMT.
Да это я на пальцах, тут лучше написано. У Out-of-Order Execution и SMT очень похожие принципы работы.
And finally we get to the killer feature of the M1. The biggest and meanest Intel and AMD microprocessor have a total of four decoders busy cutting machine code instructions into micro-ops.
But this is no match for the M1, which has an absolutely unheard of number of decoders: Eight. Significantly more than anybody else in the industry. That means it can fill up the instruction buffer much quicker.
Если код вначале загружает значение из памяти в регистр 1, потом складывает его и записывает обратно в память, а потом уже из другого адреса снова читает память в регистр 2, то может быть выгоднее изменить порядок и выполнить дважды инструкцию загрузки а потом производить операции.
Или посмотрите на это с другой стороны: у процессора есть отдельные блоки загрузки из памяти и выполнения арифметических операций. Он вполне может делать и то и другое одновременно, поэтому вместе со сложением в регистре 1, будет происходить загрузка в регистр 2.
SMT работает немного по-другом, но принцип тот же: определять, какие операции работают на разных блоках и выполнять их одновременно.
HT нужен в первую очередь для многопоточной задачи. Внутри одного потока HT не поможет никак. Весь смысл HT в том, что в более менее сложной задаче у вас будет дизбаланс или простои ядер связанные с доступом ко внешним ресурсам (сеть, диск). Поток идущий на соседнем логическом ядре может использовать исполнительные устройства, пока «основной» курит в простое.
Теперь как это сделано. Фактически дублируются регистры (общие и состояния) для ускорения переключения потоков, а исполнительные устройства сделаны в одном экземпляре. В результате старт-стоп ждущего потока и стоп-старт его соседа делаются намного быстрее, как если бы это делала ОС на уровне планировщика задач.
Да ни о чем эти не говорит: я не разработчик, а как потребителю и покупателю, преимущества HT со стороны Intel были донесены настолько витиевато, что было похоже, словно бы авторы рекламы сами не знают принципов HT.
А point моего коммента (вы же внимательно его прочли, не только начало?) был ровно в том, что без тестирования говорить о сложных и очень зависимых от задачи вещах, вроде HT, не стоит. Те речь говорить, что логические ядра не все нагружены, как бы громко, но вовсе не факт, что в каждой задаче это плохо.
Были и другие HT, от других производителей.
Объяснение HT — кривое, ибо исполняемый код — кривой.
Патч был сделан во времена AM3+, процессоры ряда «строительная техника» имеют не обычные ядра, а модули (первые 2 поколения), и количество ядер для целых чисел и для плавающей точки — разное. А ещё там есть новомодные замены FPU.
Появление такой ошибки говорит о криворукости разрабов игры, ибо для скорости нужно пользовать AVX2 + другие команды, и тогда были бы другие эффекты.
Плюс кривой код от AMD как обыденность.
Отключение HT может увеличивать производительность.
Что где включать или отключать — с этим надо возиться, а никому не охота.
Смешно, но поиски, например, информации о том, что такое hyperthreading у Intel особо не дают толковой документации
Может потому что информация перекочевала в википедию и т.п.
?
Первый ответ по делу на мой коммент, где я писал, что нужно тестировать, потому что логические ядра — не фищические ядра (а разработчики не всегда имеют прямые руки). Спасибо!
Остальным было приятно показать ЧСВ, и рассказать, как HT устроен — т.е. ответить на вопрос, который я не задавал, на который просто не мог найти ответа много лет назад.
И это — Хабр, с его вдумчивой и читающей внимательно публикой (смайлик)!
boundchecking, передача максимальной длины в функцию? Нет, не слышали!
Сигнатура функции: char* getCpuidVendor(char* vendor);
То, что это 3 int-а (а размер ведь инта высечен в камне, так?) ну как бы пока известно, но что будет через ...? Там, кстати 4 инта, но используются только 3.
В любом случае, такая сигнатура как бы намекает, что может быть по разному.
На мой программистский взгляд это дыра-дырень.
Ну и применены слова «в относительном будущем», т.е. сарказм и всё такое.
В любом случае, извиняюсь за развитие темы.
Размер int таки высечен в камне для всех распостранённых data models(хотя плюсовый стандарт и говорит об at least 16 bit для типа int).
Конечно, если собрать для Win16 — он будет 16 бит, но, мне кажется, это будет не самой большой проблемой.
А в каком-нибудь TMS320C55x sizeof(int) вообще равен 1 (что равно 16 бит).
А массив из 4 интов возвращает уже обертка над инструкцией CPUID. В целом код там сомнительного качества, но строки в 12 символов — это самая маленькая «проблема».
что будет через ...?
Будет getCpuidVendorEx
Никаких пробелм с fixed size строками нет, когда речь идет о функциях подобных этой.
проще было поместить статический буфер в саму функцию getCpuidVendor. сигнатура и модель процессора меняться не могут.
P.S. Ещё придумалось: можно ли сейчас на двухпроцессорных рабочих станциях ставить процессоры разной модели. И перебрасывается ли системой процесс между ядрами разных процессоров или только в пределах одного.
А если забить на обратную совместимость инструкций в x86, то программа просто не дойдёт до этой строчки, так как ей до этого надо исполнить тысячи других инструкций. Гарантия, что cpuid возвращает 12 байт на запрос вендора примерно такая же как, что mov выполняет копирование значения из источника в приёмник.
Физических ядер и так дофига, неужто не хватило?
Нагрузка в 100% CPU vs 60% CPU это конечно хорошо, но можно привести в статье насколько это влияет на FPS?
в компании для тестирования игры может быть всего две-три типовых конфигурации компьютера
Все же надо было взять комментарий у разработчика в КРУПНОЙ компании, коей является CD Projekt(штат — 1044 человека).
Я полагаю, что этот косяк, как и сотни других связаны с низким уровнем разработки и торопливостью при релизе Cyberpunk 2077. Обвинять AMD в чем-то — это все равно, что взять код со Stackoverflow и обвинять его, что код работает не так, как нужно.
Все же надо было взять комментарий у разработчика в КРУПНОЙ компании
Человек работает в компании, производящей ААА игры.
коей является CD Projekt(штат — 1044 человека).
Но как раз из статьи и становится понятно, что такие промахи случаются даже в крупных компаниях.
Я полагаю, что этот косяк, как и сотни других связаны с низким уровнем разработки и торопливостью при релизе Cyberpunk 2077
3,5 бага в релизе и совершенно недосягаемый уровень игры нельзя назвать низким уровнем разработки.
Чего чего чего????
3,5 бага?)
А ты в неё играл?)
Игра сырая, что аж смотреть на неё больно
нпс просто маникены, уровень сложность вообще смешон
Видны «затычки» в механиках игры
Как тебе соперники в гонках, которые у тебя за спиной телепортируются? Ты сейчас серьезно назвал это шедевром?
А как тебе вдали невидимый поток машин (Аля пробка), которых ты никогда не догонишь)
И, кстати, это есть в пустыни, где машин вообще нет
Все механики 2010 года
Игра сделана ужасно
Она очень сырая
Дак ещё и про общее кол-во багов молчу
(А ещё о том, что это тупо ведьмак в сеттинге киберпанка, который кстати они даже осилить не смогли, понаприглашать кучу знаменитостей, а где куча отсылок к культуре этой тематике? Нет, мы бадкомедиана заплатим лучше где-то в игре, такой ор)
Тут ни шедевров нет, и прорыва тем более нет
Игра 200кк стоит, а такая шляпа вышла
Стадно, больше нечего сказать.
Эта особенность на 99% должна была быть выявлена на ранних этапах тестирования и слабо верится что это случайность.
У меня сложилась проблема при удаленной игре через Parsec Gaming или Steam Remote Play, в игре просто отключены виртуализированные устройства ввода. Молодцы с Reddit сделали самописный патч, и всё заработало.
Вряд ли это связано.
Можно самим пропатчить, можно взять набор фиксов:
https://github.com/yamashi/PerformanceOverhaulCyberpunk
Заголовок натянут, как сова.
Ни черта они толком не тестировали, всё.
А иначе электроны виноваты, вместе с Максвеллом )
Ссылка на репозиторий: github.com/Pavel3333/Cyberpunk-2077-AMD-Optimization-Patcher
Релизы (сейчас актуальная версия v1.01): github.com/Pavel3333/Cyberpunk-2077-AMD-Optimization-Patcher/releases
В 2020 сложно довериться стороннему софту для такого, тем более что в .NET исходниках много мусора и сложно найти код самого патчера.
Не очень понимаю, зачем вы тяните скомпилированные .dll в /packages/Newtonsoft.Json.12.0.3/
Ну и традиционная шутка: переписать бы это на раст...
На всякий случай рекомендую людям патчить .exe вручную HEX-редактором.
Патчер писал для обычных юзеров, ибо многие даже толком не знают, что за HEX-редакторы и на каких дубах вечнозеленых они растут.
Newtonsoft.Json — это NuGet-пакет. С учётом того, что это мой первый за n лет проект на C#, то я проверил, что будет, если не взять папку packages — оказалось, что пакет не подхватится автоматически. Зацепил его на всякий случай.
Код патчера старался расположить в самом Patcher.cs, всё остальное — хэндлеры в Patcher.Handlers.cs, сигнатурки в Patcher.Signatures.cs, дизайнер в Patcher.Designer.cs…
Библиотека от AMD стала причиной плохой производительности процессоров AMD в Cyberpunk 2077