Как стать автором
Обновить

Комментарии 90

Заговор оптимизации под процессоры Intel настолько велик, что в нем участвует даже AMD :)

еще остались люди которые не забыли, что когда то интел делали хорошие процессоры, адекватные стоимости:)

Что забавно — многие утверждают, что именно сейчас процы Интел это бестбай за бакс :)
А у АМД пока и новинки стоят как новинки, и на прошлые модели цены не понижают.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

Magic numbers и сырые строки, конечно удручают.
А так, всё как у людей.

Думаю, надо просто убрать эту функцию и все будет ок. Пусть разработчик пишет свою реализацию на основе модели проца и числа ядер.
Завтра big.LITTLE может появиться и в windows, в любом случае планировщику приложения надо понимать, что не все ядра имеют одинаковую производительность.

Зачем этот костыль в десктопах?
Десктопам не нужна автономность.

Но windows 10 сейчас работает и на ноутбуках и на суперавтономных планшетах. На них уже от батарейки надо во время бодрствования экономить.

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()» и получить самодокументирующийся код
если ничего не путаю, то на x86 результат cpuid(0) возвращается на трёх регистрах по 4 байта — это 12 байт и терминирующий ноль, итого 13.

Только непонятно почему "ошибка"? Это просто такое поведение по умолчанию. Для части задач подходит для части нет. С учётом того что библиотека "для одного приложения" то подход по умолчанию выглядит логичным.

Ошибка, потому что для подавляющего большинства ситуаций, лучше, если число потоков планировщика равно числу логических ядр. Глупо замедлять 90+% конфигураций.

Подозреваю что когда этот код писался — большинством были Bulldozer'ы.

Я тоже так думал, но статья раскрыла этот вопрос.
Похоже, я забыл дать на нее ссылку (

Я конечно уже давно понимаю, что понимать то что ты пишешь сейчас не модно. И разработчиком может стать даже дворник с 3 классами пту. Но как можно было умудрится в строчке 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;
}

У меня ryzen 5 1600, игра изначально задействует все 12 логических ядер. Я даже не всякий случай правил исполняемый файл игры, разницы замечено не было.

Это вроде пофиксили в патче 1.05, который как раз 20 декабря вышел. Он исправил проблему статьи для 4 и 6 ядерных Ryzen.

Я комментарий оставлял ещё 16 декабря по-моему, его просто очень долго одобряли :)
В любом случае у меня всё было ок, с самой первой версии.

Так этот патч наоборот чинил использование логических ядер для Intel. Для АМД ничего не изменилось.

Ага, там для всех вендоров, кроме АМД, count = logical; но товарищу важнее было назвать меня дворником, чем разобраться)

Смешно, но поиски, например, информации о том, что такое hyperthreading у Intel особо не дают толковой документации, особенно от самого Intel. Как не дают и ответа, как можно повысить производительностью, исполняя работу для двух ядер на одном.


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


Здесь (в оригинале, конечно) призывается масштабировать ПО на число логических ядер. Те автор верит, чтт лигияеское не худе, чем физическое. Значит ли это, что 2 ядерный процессор вдруг стал 4-ядерным? Очевидно, нет, и все как-то сложнее.


Что дает тот же вывод, чтт и в приведенной автором статье — тестируйте!

Грубо говоря, ядро может выполнять разные типы задач. Допустим, сложение целых чисел и сложение чисел с плавающей запятой. В обычной ситуации эти задачи будут выполняться по очереди. То есть, один из блоков будет простаивать. Логично попробовать загрузить ядро по полной и дать ему обе задачи одновременно. Но подходит такое не для каждого алгоритма. Допустим, в программе нет вычислений с плавающей запятой. Тогда ускорение получить не выйдет.

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

Яблочный М1, кстати, делает это еще агрессивнее: в архитектуре ARM можно иметь SMT сразу в 4 потока. Причем потенциал больше, чем в х86 за счет более простого декодера коменд (из-за однородности их размера).

Ну IBM Power8 на одном ядре умел выполнять 8 потоков, так что всё новое — это хорошо забытое старое)
Причем потенциал больше, чем в х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 в том, что в более менее сложной задаче у вас будет дизбаланс или простои ядер связанные с доступом ко внешним ресурсам (сеть, диск). Поток идущий на соседнем логическом ядре может использовать исполнительные устройства, пока «основной» курит в простое.
Теперь как это сделано. Фактически дублируются регистры (общие и состояния) для ускорения переключения потоков, а исполнительные устройства сделаны в одном экземпляре. В результате старт-стоп ждущего потока и стоп-старт его соседа делаются намного быстрее, как если бы это делала ОС на уровне планировщика задач.
мне казалось оно чуть сложнее. У ядра есть регистровый файл (и его размер больше, чем количество РОНов и прочего) и уже он делится на двоих. Ещё можно вспомнить, что со времён Pentium внутри ядра несколько конвейеров (U и V были на пне), что позволяло исполнять более одной инструкции за такт. Но дело это не простое и 100% утилизация такой схемы — явление довольно редкое. А вот если эти конвейеры нагрузить разными потоками, то можно добиться более плотной утилизации.

Да ни о чем эти не говорит: я не разработчик, а как потребителю и покупателю, преимущества HT со стороны Intel были донесены настолько витиевато, что было похоже, словно бы авторы рекламы сами не знают принципов HT.


А point моего коммента (вы же внимательно его прочли, не только начало?) был ровно в том, что без тестирования говорить о сложных и очень зависимых от задачи вещах, вроде HT, не стоит. Те речь говорить, что логические ядра не все нагружены, как бы громко, но вовсе не факт, что в каждой задаче это плохо.

Intel эту HT лицензировала у AMD.
Были и другие HT, от других производителей.
Объяснение HT — кривое, ибо исполняемый код — кривой.
Патч был сделан во времена AM3+, процессоры ряда «строительная техника» имеют не обычные ядра, а модули (первые 2 поколения), и количество ядер для целых чисел и для плавающей точки — разное. А ещё там есть новомодные замены FPU.
Появление такой ошибки говорит о криворукости разрабов игры, ибо для скорости нужно пользовать AVX2 + другие команды, и тогда были бы другие эффекты.
Плюс кривой код от AMD как обыденность.
Отключение HT может увеличивать производительность.
Что где включать или отключать — с этим надо возиться, а никому не охота.
Смешно, но поиски, например, информации о том, что такое hyperthreading у Intel особо не дают толковой документации

Может потому что информация перекочевала в википедию и т.п.
?

Тут действительно надо тестировать. Например, escape from tarkov — с НТ бывают мини фризы, которые убираются именно отключением этого НТ. Более того, прямо в игре есть галка «использовать реальные ядра», но именно на амд бывает что не работает, нужно в биосе выключать, и тогда фризы пропадают. И тут уже не важно, даёт ли прирост НТ, с ним существенно падает комфорт игры. Такая вот особенность.

Первый ответ по делу на мой коммент, где я писал, что нужно тестировать, потому что логические ядра — не фищические ядра (а разработчики не всегда имеют прямые руки). Спасибо!


Остальным было приятно показать ЧСВ, и рассказать, как HT устроен — т.е. ответить на вопрос, который я не задавал, на который просто не мог найти ответа много лет назад.


И это — Хабр, с его вдумчивой и читающей внимательно публикой (смайлик)!

Была ошибка в камнях при работе HT (ранние первые райзены). Исправляется (иногда) обновлением прошивки процессора. Обновите БИОС МП, может, поможет. Проверьте с более новым процессором (Ryzen 1xxx -> 2xxx -> ...).
Вот будет весело (в относительном будущем), если getCpuidVendor вернёт строку длинее 12 символов!
boundchecking, передача максимальной длины в функцию? Нет, не слышали!
cpuid — это команда процессора, которая возвращает 12 байт в трёх 32-битных регистрах
SergeyMax, заранее извиняюсь за некоторую назойливость :(.

Сигнатура функции: char* getCpuidVendor(char* vendor);
То, что это 3 int-а (а размер ведь инта высечен в камне, так?) ну как бы пока известно, но что будет через ...? Там, кстати 4 инта, но используются только 3.
В любом случае, такая сигнатура как бы намекает, что может быть по разному.
На мой программистский взгляд это дыра-дырень.

Ну и применены слова «в относительном будущем», т.е. сарказм и всё такое.
В любом случае, извиняюсь за развитие темы.

Размер int таки высечен в камне для всех распостранённых data models(хотя плюсовый стандарт и говорит об at least 16 bit для типа int).
Конечно, если собрать для Win16 — он будет 16 бит, но, мне кажется, это будет не самой большой проблемой.

BTW, в микроконтроллерах AVR он вполне себе 16 бит. Что вызывает недоумение у некоторых молодых программистов.
А в каком-нибудь TMS320C55x sizeof(int) вообще равен 1 (что равно 16 бит).

ya_frosia: Связка ломов, как правило, тонет.
alexei: ya_frosia: Но в ртути прекрасно плавает.
zoogenic: alexei: Но если ломы урановые, то и во ртути тонут.
alexei: zoogenic: сам топи урановые ломы в ртути.

Прежде чем занудствовать, изучили бы предмет. Не в 3 интах, а именно что в 3 32-битных регистрах EBX, EDX, ECX (in that order)
А массив из 4 интов возвращает уже обертка над инструкцией CPUID. В целом код там сомнительного качества, но строки в 12 символов — это самая маленькая «проблема».
что будет через ...?

Будет getCpuidVendorEx
Никаких пробелм с fixed size строками нет, когда речь идет о функциях подобных этой.

проще было поместить статический буфер в саму функцию getCpuidVendor. сигнатура и модель процессора меняться не могут.

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

P.S. Ещё придумалось: можно ли сейчас на двухпроцессорных рабочих станциях ставить процессоры разной модели. И перебрасывается ли системой процесс между ядрами разных процессоров или только в пределах одного.
CPUID на запрос вендора процессора возвращает 3 32-битных значения в 3 32-битных регистрах. И так будет всегда и на любом процессоре x86 начиная от первого поддерживающего инструкцию cpuid и заканчивая последним выпущенном x86-совместимым процессором в мире. Если захотят возвращать более длинную строку производителя, то будет введена другая инструкция (или другой код запроса к cpuid). Соответственно, функция этого запроса уже будет называться не getCpuidVendor, а как-то иначе.

А если забить на обратную совместимость инструкций в x86, то программа просто не дойдёт до этой строчки, так как ей до этого надо исполнить тысячи других инструкций. Гарантия, что cpuid возвращает 12 байт на запрос вендора примерно такая же как, что mov выполняет копирование значения из источника в приёмник.
использование процессора увеличилось — а игра то пошла шустрее?
Физических ядер и так дофига, неужто не хватило?

Да, пишут что стало заметно лучше. Сам еще не пробовал, у меня R5 1600x, как раз

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

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

Нагрузка в 100% CPU vs 60% CPU это конечно хорошо, но можно привести в статье насколько это влияет на FPS?

Значительно, +10-15 у многих, особенно к минимальному. Понятно, что на 5950х патч ускорения не даст, но на стандартных 6-8 ядерных Райзенах с мощной видеокартах эффект виден сразу.
Комментарий разработчика таки доставил:
в компании для тестирования игры может быть всего две-три типовых конфигурации компьютера

Все же надо было взять комментарий у разработчика в КРУПНОЙ компании, коей является CD Projekt(штат — 1044 человека).
Я полагаю, что этот косяк, как и сотни других связаны с низким уровнем разработки и торопливостью при релизе Cyberpunk 2077. Обвинять AMD в чем-то — это все равно, что взять код со Stackoverflow и обвинять его, что код работает не так, как нужно.
НЛО прилетело и опубликовало эту надпись здесь

разве факторио был не в раннем доступе?


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

Все же надо было взять комментарий у разработчика в КРУПНОЙ компании

Человек работает в компании, производящей ААА игры.


коей является CD Projekt(штат — 1044 человека).

Но как раз из статьи и становится понятно, что такие промахи случаются даже в крупных компаниях.


Я полагаю, что этот косяк, как и сотни других связаны с низким уровнем разработки и торопливостью при релизе Cyberpunk 2077

3,5 бага в релизе и совершенно недосягаемый уровень игры нельзя назвать низким уровнем разработки.

НЛО прилетело и опубликовало эту надпись здесь

Чего чего чего????
3,5 бага?)
А ты в неё играл?)


Игра сырая, что аж смотреть на неё больно
нпс просто маникены, уровень сложность вообще смешон
Видны «затычки» в механиках игры
Как тебе соперники в гонках, которые у тебя за спиной телепортируются? Ты сейчас серьезно назвал это шедевром?
А как тебе вдали невидимый поток машин (Аля пробка), которых ты никогда не догонишь)
И, кстати, это есть в пустыни, где машин вообще нет
Все механики 2010 года
Игра сделана ужасно
Она очень сырая
Дак ещё и про общее кол-во багов молчу
(А ещё о том, что это тупо ведьмак в сеттинге киберпанка, который кстати они даже осилить не смогли, понаприглашать кучу знаменитостей, а где куча отсылок к культуре этой тематике? Нет, мы бадкомедиана заплатим лучше где-то в игре, такой ор)


Тут ни шедевров нет, и прорыва тем более нет
Игра 200кк стоит, а такая шляпа вышла
Стадно, больше нечего сказать.

А самое главное — она скучная блин. Как будто юбисофт какой то. Полтора квеста из сюжетки, и миллион дополнительных абсолютно одинаковых жёлтеньких маркеров на карте.

может под недосягаемым уровнем имеется ввиду заработанное на хайпе бабло?

Тут СХД за сотни килобаксов баксов не стартуют с фирменными SSD некоторых моделей, а вы про игроделов…
Библиотека на то и библиотека, что ей пользуются как неким готовым объектом. CDPR используют тысячи библиотек, как они могли за всем уследить? Налицо небрежное отношение авторов библиотеки
С одной стороны — да, с другой стороны — это не какая-то скрытая штука, отдел тестирования просто ОБЯЗАН обратить внимание на неполную утилизацию CPU.

Эта особенность на 99% должна была быть выявлена на ранних этапах тестирования и слабо верится что это случайность.

это геймдев, где особенностей больше, чем волос в бороде у главного разработчика.

Это правило действует когда ты работаешь на готовом движке (UE или Unity), это позволяет тебе немного абстрагироваться.

Ну скорее всего проблема куда глубже. Получить полную загрузку процессоров Ryzen в играх реально тяжело. И теперь понятно почему :)))
А мы наоборот, на intel в своём использующем OpenCV софте по дефолту делили число ht-ядер пополам чтобы получить число эффективно работающих процессов.
А как применить данную настройку? Ждать патч от разработчиков или можно самим перепатчтить?
У меня сложилась проблема при удаленной игре через Parsec Gaming или Steam Remote Play, в игре просто отключены виртуализированные устройства ввода. Молодцы с Reddit сделали самописный патч, и всё заработало.

Вряд ли это связано.

Заголовок натянут, как сова.
Ни черта они толком не тестировали, всё.
А иначе электроны виноваты, вместе с Максвеллом )

Написал патчер для Киберпанка. Сигнатуры актуальны на момент написания комментария, как и сама проблема. При запуске патчер подтягивает сигны с репозитория, потому после каждой обновы игры можно не перекачивать сам патчер. Если, конечно, не было какой-то большой переделки.

Ссылка на репозиторий: 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…
Наверно патч уже неактуален, так как проблема исправлена разработчиками в 1.05.
Нет, всё протестировано вчера на версии 1.05 (с утренней обновы), на 8-ядерных AMD Ryzen 7 2700X нагрузка на половину логических ядер точно такая же, как на скринах в посте. Патч актуален. См. результаты замеров в моём посте
Так патч 1.05 включил логические ядра для 4 и 6 ядерных. А для 8+ по их данным выгоды от этого действия в принципе нет. Так что на 2700X картинка измениться и не должна была. Вопрос в том, существенно ли это влияет на ФПС. Вы можете сравнить на вашей конфигурации?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации