Войти
ПрограммированиеФорумГрафика

Recursive Tile-based architecture (комментарии) (8 стр)

Страницы: 13 4 5 6 7 8
#105
16:56, 29 янв 2022

}:+()___ [Smile]
> ведь после этого надо для каждого найденного пересечения запустить шейдер материала и существующие SIMD блоки тут плохо подходят.
Если не упарываться в принципиально уникальные материалы для каждой точки пространства, то в целом можно какую надо информацию сохранить и потом сделать fullscreen-pass шейдинга.
> От того, что ты заменишь стандартный ALU на специализированный целочисленный вычислительный блок, ты улучшения на порядок не получишь. В лучшем случае раза в два
Ну, не скажи. У AMD вроде как больше чем в два раза буст, хотя и вряд ли на порядок. Правда у них не совсем ALU, а как бы новый вид текстурного семплера :)

#106
17:53, 29 янв 2022

Mobile Developer
> Не понял, как он тут поможет.
То, что каждый луч может считаться независимо без каких-либо штрафов на когерентность. Причем, от начала (корня BVH) и до конца (шейдера материала с текстурами, возможно даже после нескольких отражений) без каких-либо промежуточных буферов с перекидыванием лучей между разными исполнительными устройствами. К тому же, архитектура универсальна, может пригодиться не только для рейтрейсинга.

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

> Намного больше. Там же не 32 битные переменные используются.
От битности зависит только размер ALU в транзисторах, а не производительность. Конечно, мелких ALU можно побольше напихать, но тут все упирается в обвязку.

> Простаивание ALU не потребляет энергии.
Как раз в старой парадигме, точнее в толстых техпроцессах. Есть два основных источника потерь в микросхемах: токи утечки и токи переключения. Первые текут всегда, если кусок чипа полностью не обесточен, вторые — при переключениях транзисторов. Причем, чем более мелкий техпроцесс, тем больше доля постоянного тока утечки (насколько я помню, в современных техпроцессах это ~60%). Вот эти 60% и будут впустую жарить чип, либо надо отключать от питания простаивающие блоки, что невозможно сделать быстро и допустимо только при полностью отсутствующей нагрузке в течение некоторого времени.

> Это отдельный модуль, он связан с обычными компутюнитами только командной шиной.
А данные ему не надо передавать? У него, как минимум, свой порт доступа к памяти, который надо увязать с существующими. А это дополнительный роутинг, увеличенные промежуточные буферы и очереди, возможно, с дополнительными портами чтения/записи. Причем, чем больше новых исполнительных устройств, тем больше всего надо (поэтому, например, один порт памяти с одним ALU, обрабатывающим пачки по 32 ребенка за раз, лучше эквивалентных по вычислительной мощности 16 портов памяти с таким же ALU, обрабатывающим детей парами).

phridrich
> можно какую надо информацию сохранить и потом сделать fullscreen-pass шейдинга.
Смысл рейтрейсинга в том, что цвет поверхности влияет на цвет последующих отражений. Это никакой постобработкой не имитировать.

> Ну, не скажи. У AMD вроде как больше чем в два раза буст, хотя и вряд ли на порядок.
Это экстенсивно, за счет количества устройств. Я говорю только про замену 1:1.

#107
(Правка: 18:11) 18:11, 29 янв 2022

}:+()___ [Smile]
> То, что каждый луч может считаться независимо без каких-либо штрафов на
> когерентность.
Штраф на когерентность возникает из-за рандомного доступа в память. Тут он никуда не девается.

>шейдера материала с текстурами, возможно даже после нескольких отражений
Как связаны шейдеры материала с BVH?

>К тому же, архитектура универсальна, может пригодиться не только для рейтрейсинга.
Мне кажется, что ты чего-то не понимаешь.

>Это уже мультфильм будет какой-то, непонятно, зачем ему рейтрейсинг, в принципе.
Какой дурак будет использовать крайне ограниченный бюджет лучей для когерентных эффектов? Всё что хорошо видно - рисуется растеризацией. Там и текстуры и прочее.
Всякие фоновые вещи, GI, color bleeding делаются рейтрейсингом, и ни точность, ни текстуры здесь особо не важны.

>От битности зависит только размер ALU в транзисторах, а не производительность.
В случае мобил ключевым фактором является потребление энергии, оно зависит от количества транзисторов.
Производительность так же зависит, т.к. малобитные операции можно делать сложнее. У нас тут всего несколько задач: пересечение с боксом, пересечение с треугольником и пара вспомогательных. Никаких больше нет. А эти задачи, в случае с малобитностью можно сворачивать в одну команду. Если разрядность большая - сложность там квадратичная и площадь сильно растёт, поэтому её приходится раскладывать на подоперации и на каждую тратить такты.

>либо надо отключать от питания простаивающие блоки, что невозможно сделать быстро и допустимо только при полностью отсутствующей нагрузке в течение некоторого времени.
Сюрпрайз, который упоминался уже много раз - у тебя отдельный юнит.
Он фигачит по полной 5% времени кадра, а потом выключен.

>А данные ему не надо передавать?
Надо, но не так как ты понимаешь. У этого юнита вся BVH на борту. Речи не идёт о том, что он стучится в основную память для траверсинга. Из памяти он вычитывает треугольники, но это как раз происходит большими блоками.

#108
18:40, 29 янв 2022

}:+()___ [Smile]
> Смысл рейтрейсинга в том, что цвет поверхности влияет на цвет последующих отражений. Это никакой постобработкой не имитировать.
А, ты имеешь в виду весь путь луча сразу просчитать одним ядром? Если делать пазтрейсинг так, как сейчас принято - у тебя будет жуткий дисбаланс в загрузке ядер. Обычно после трейсинга лучей и шейдинга делают компакцию новых лучей (а далеко не каждый путь испускает новый луч), чтобы хоть как-то скрасить ситуацию.
> Это экстенсивно, за счет количества устройств. Я говорю только про замену 1:1.
Я тоже о ней говорю. Хотя пруфов у меня нет, так что неважно.

#109
21:59, 29 янв 2022

Mobile Developer
> Штраф на когерентность возникает из-за рандомного доступа в память.
Штраф на когерентность возникает в SIMD (ибо треды физически не могут исполнять разные инструкции) и у кешей (ибо бесполезны). Для основной памяти когерентность, скорее, в минус идет: если пачка тредов одновременно тыкнется в одинаковую ячейку памяти, случится bank conflict и они будут ждать. Чтобы этого не случалось, в SIMD архитектурах делают объединение запросов тредов в пределах варпа (причем, в ранних видеокартах распознавался только самый примитивный шаблон, когда запросы идут строго подряд).

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

> Мне кажется, что ты чего-то не понимаешь.
Это я про свою идею: throughput-oriented scalar CPU.
Твои гипотетические мобилки с мультяшным рейтрейсингом, мне кажется, не взлетят.

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

> Всякие фоновые вещи, GI, color bleeding делаются рейтрейсингом, и ни точность, ни текстуры здесь особо не важны.
То есть, по факту, твой рейтрейсинг — это Fixed Function с крайне примитивными материалами (кстати, даже просто запросить цвет поверхности — это некогерентный доступ к памяти). На мой взгляд, расширить функции обработчика треугольников на произвольные шейдеры просто напрашивается, заодно сэкономив на проброс лучей в Generic Compute Units.

> Он фигачит по полной 5% времени кадра, а потом выключен.
Это только если у тебя получится собрать эти 5% в одну непрерывную пачку и не окажется, что твой юнит постоянно ждет данных снаружи. А если получится, то непонятно, почему ты решил добровольно урезать свой итак маленький лимит лучей в 20 раз?

> У этого юнита вся BVH на борту.
Так вся, или только кеш? Но, в любом случае, доступ в память ему нужен, даже если редко, и транзисторы на это дело выделить придется. Наоборот, будет хуже, если эти транзисторы будут бесполезно простаивать.

phridrich
> Если делать пазтрейсинг так, как сейчас принято - у тебя будет жуткий дисбаланс в загрузке ядер.
Если лучи изначально случайно по ядрам раскидать, то не будет. Плюс еще можно бесшовную миграцию простаивающих потоков аппаратно реализовать, они маленькими будут (16/32 64-битных регистра, никаких SIMD).

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

> Я тоже о ней говорю. Хотя пруфов у меня нет, так что неважно.
Ну так целочисленное сложение — это 1–2 такта, FMA — 4–5 такта, как и целочисленное умножение, кстати.
В среднем, раза в два разницы.

#110
23:13, 29 янв 2022

}:+()___ [Smile]
> возникает в SIMD
Риторический вопрос: а они где-то кроме CPU ещё остались?
Комментарий: а в случае организованного рейтрейсинга команды одинаковые, в исполнении рейтрейсинга по сути нет ветвления. Оно есть в дереве, но не на исполняемом уровне.
Ты Эмбри смотрел?

>Они требуются в процессе обработки одного луча. Если архитектура имеет достаточно универсальные вычислительные единицы, имеет смысл обрабатывать все сразу, без переброса между разными исполнительными устройствами и связанных с этим накладных расходов.
Переброс имеет смысл, потому, что оптимизированное для рейтрейсинга решение многократно быстрее реализации на компутшейдерах.
Тебя же не смущает, что управление передаётся при запросе текстур?
В случае же рейтресинга вопрос стоит ребром: универсальностью ты убиваешь (реалтаймовое) решение вообще. Это как во времена относительно ранних видях делать самому растеризацию на компутшейдерах ради универсальности.

>мультяшным рейтрейсингом
Там не мультяшный, а обычный практический hybrid. Чтение текстур при некогерентном рейтрейсинге не горит, а когерентный на мобилах не нужен.

>На мой взгляд, стохастические эффекты мобилы не вытянут
Не вытянут.

>А вот красивое околозеркальное отражение от лужи воды не помешает, а для него текстуры нужны.
Этот вопрос давно и прекрасно решается обычной растеризацией, и оптимизируется технологией описанной в субже.

Что касается рейтрейсинга который я проектировал - то он нужен для глобальной пространственно-оптимизированной иллюминации: на разных вариантах сюрфелей, радиосити и т.п.
Такой рейтрейсинг может создать игру света на мелких деталях, добавить спекулярную иллюминацию, color-bleeding и прочее.

>То есть, по факту, твой рейтрейсинг — это Fixed Function
Нет, обычный рейтрейсинг с тем ограничением, что он некогерентный. С материалами он вообще никак не пересекается, его задача найти много пересечений. Юзер запросил пересечение со сценой - получил дистанцию, ID объекта, примитива, U и V. Что там дальше - уже не моё дело.

>произвольные шейдеры просто напрашивается,
Сугубо с доп.целями. Это не может быть основным инструментом, так как мы тут перестаём обеспечивать минимальную производительность.

>Это только если у тебя получится собрать эти 5% в одну непрерывную пачку и не окажется, что твой юнит постоянно ждет данных снаружи
Это уже задача юнита. Предполагается, что лучи фигачатся в ходе генерации GI, и может для ещё какой отдельной задачи.

>А если получится, то непонятно, почему ты решил добровольно урезать свой итак маленький лимит лучей в 20 раз?
Этот самый лимит посчитан с учётом обрезания в 20 раз. Минимальная цель - миллион лучей на кадр, без потери производительности на компутшейдерах (т.к. рейтрейсинг не основная задача).

>Так вся, или только кеш?
Именно прямо кеш, как посредник между юнитом и памятью, в случае некогерентного рейтрейсинга бесполезен (кроме самой верхушки дерева). BVH большой, траверсер каждый раз бегает разными путями и из каждого блока памяти берёт всего несколько байт. Т.е. MMU в случае рейтрейсинга это тормоз.
В предложенном решении мы сжимаем BVH в 5 раз, и на ограниченном количестве полигонов (500К штук) позволяем ему вписаться, с небольшим запасом, в 1мб быстрой памяти. Она распределяется между сотнями небольших блоков, что позволяет минимизировать конфликты. Таким образом любой обход BVH останется внутри кеша и во внешнюю память не ходит. TLAS обрабатывается на компут юнитах, его BVH не сжатая. Луч дойдя до листов TLAS трансформируется и получает информацию о том, к какому блоку BLAS он должен перейти (treeletId). Компут юнит отдаёт запрос в шедулер рейтрейсного юнита. В типичной ситуации один луч загрузит 2-3 траверсных блока содержащих соответствующий BLAS.
Поскольку при некогерентном рейтрейсинге пускают не один луч, а несколько десятков (для пространственно-оптимизированного GI), каждый луч будет идти в своём направлении и станет грузить разные блоки. Каждый блок в режиме мультитрединга может обрабатывать несколько лучей. Юнит в целом будет нагружаться несколькими десятками существующих компут юнитов.
Компут юнит отдавший задачу на трассировку - переключается на другую задачу (это стандартная фича, если кто не знал).
Указанные константы это образец кажущийся реалистичным на момент 2021 года, в реальном продукте должна быть осуществлена балансировка, в соответствии с требованиями конкретной платформы.

#111
23:16, 29 янв 2022

}:+()___ [Smile]
> FMA — 4–5 такта
В нашем случае вся проверка пересечения бокса с лучом и сопутствующими этому операциями (про которые тут говорили, что это медленно) должно занимать похожее количество тактов, т.к. вычисления целочисленные и малобитные, много проще, чем флоатные.

#112
0:17, 30 янв 2022

}:+()___ [Smile]
> Если лучи изначально случайно по ядрам раскидать, то не будет. Плюс еще можно бесшовную миграцию простаивающих потоков аппаратно реализовать
Не уверен что это сильно поможет - даже если ты объединишь ядра в большие группы - какие-то группы все равно будут справляться быстрее чем другие. А делать шеудлинг - сложно и скажется на производительности/потребляемой мощности.
> 16/32 64-битных регистра
Это ты очень оптимистично прикинул :) На шединг может много регистров понадобиться.
> Вот вот, и эта хрень жрет, как минимум, половину производительности.
Ну нет. Она занимает некоторое время, но на больших сценах рейтрейсинг есть рейтрейсинг.

#113
(Правка: 3:07) 3:01, 30 янв 2022

Mobile Developer
> Риторический вопрос: а они где-то кроме CPU ещё остались?
Все GPU, в том числе мобильные, — это SIMD, у всех высокопроизводительных CPU есть векторные расширения (даже в телефонах!), всякие нейроускорители — это вариации на тему. Так что это не "где еще остались", а "где еще нет?"

> в случае организованного рейтрейсинга команды одинаковые, в исполнении рейтрейсинга по сути нет ветвления.
Поэтому и пытаются его реализовывать на современных видеокартах, иначе было бы совсем без шансов. Но, на самом деле, ветвления есть: проверили мы треугольники в текущем листе, пересечения не нашли, надо переходить к следующему — а это ветвление. Можно, конечно, обновить начало луча и запустить его снова на следующей итерации, но это повторный проход по BVH. И еще далеко не всегда получается сделать идеально сбалансированное дерево, особенно если много динамики.

> Переброс имеет смысл, потому, что оптимизированное для рейтрейсинга решение многократно быстрее реализации на компутшейдерах.
За счет чего? В современных процессорах ALU занимают от силы 5% кристалла, остальное — это системы подготовки и хранения данных для них. Соответственно, если заменить ALU на магически оптимизированные, мгновенно выдающие результат, то скорость всего чипа изменится слабо, ибо это не узкое горлышко.

> Юзер запросил пересечение со сценой - получил дистанцию, ID объекта, примитива, U и V. Что там дальше - уже не моё дело.
Ну и упрется производительность в то, что дальше, вместо того, чтобы считать еще лучи.

> Это не может быть основным инструментом, так как мы тут перестаём обеспечивать минимальную производительность.
Так мы же тут выяснили, что у нас есть 20-кратный запас по производительности. Задействуем его под минимальные шейдеры и получим итоговое десятикратное увеличение количества лучей.

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

> каждый луч будет идти в своём направлении и станет грузить разные блоки.
Без какого-то продвинутого шедулера, который будет динамически переключать блоки (и, например, автоматически размножит корневой обработчик) не взлетит. Ибо пользователь всегда найдет какой-нибудь угол, в котором у него все упрется в один юнит и будет писать, что все тормозит.

> вычисления целочисленные и малобитные, много проще, чем флоатные.
Всего в 2 раза быстрее по latency при той же обвязке. На транзисторах, казалось бы, можно выиграть больше, но, при сравнении с вариантом "переиспользовать ALU стандартных шейдеров", все становится не так однозначно. Тем более, нет особой разницы, будет ли оно считать 5 или 50 тактов, если все равно сначала надо ждать данных треугольника из памяти по 500 тактов.

phridrich
> какие-то группы все равно будут справляться быстрее чем другие.
Будем генерировать лучи в процессе и кидать их на свободные ядра.

> А делать шеудлинг - сложно и скажется на производительности/потребляемой мощности.
Перекинуть ожидающий тред — это просто переслать его регистровый файл. Без продвинутого шедулинга с приоритетами все равно никуда — один надолго зависший тред убъет всю производительность.

> На шединг может много регистров понадобиться.
Пускай скидывает в память, на throughput это не сильно скажется, при условии, что полосы будет хватать.

#114
3:40, 30 янв 2022

}:+()___ [Smile]
> Все GPU, в том числе мобильные, — это SIMD
Тут возможно какая-то путаница. У них есть SIMD для выполнения отдельных векторных команд и только. Это условно может тебе немного помочь с реализацией отдельной функции, но это очень низкий уровень, относительно того, что мы обсуждаем. Сейчас разные юниты работают практически независимо друг от друга, хотя когда-то на заре было такое, что они работали синхронно, выполняя одну команду на несколько юнитов.

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

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

> Ну и упрется производительность в то, что дальше, вместо того, чтобы считать
> еще лучи.
Тут кажется есть недопонимания порядков величин. Траверсинг лучей это крайне затратная процедура. Обработка пересечения на её фоне малозаметна. Растеризация по смыслу тоже является рейтрейсингом, каждый пиксель - это точно такая же точка пересечения. И ничего, она вполне способна обрабатывать сотни миллиардов запросов к текстурам.
В случае мобилы речь идёт о миллионе/двух лучей на кадр, грузить текстуры для фоновых эффектов смысла нет - девайс вполне справится.

> Так мы же тут выяснили, что у нас есть 20-кратный запас по производительности.
> Задействуем его под минимальные шейдеры и получим итоговое десятикратное
> увеличение количества лучей.
Да нет. Я несколько страниц назад приводил статистику по нагрузке при траверсинге лучей. Миллион лучей это 50-100 гигафлоп и 25-50 гигабайт. Представь, что у тебя хотя бы 30 кадров и что то ещё нужно считать (растеризацию, отражения, тени, анимации, постпроцессинг и т.п.) итого мы уходим в 30+ терафлоп. У тебя много таких девайсов? И это для всего ляма лучей на кадр, меньше одного луча на точку.
Специализированная железка, по типу предлагаемой, снижает затраты (условно) до 300гигафлоп. Это уже вполне укладывается в рамки прошлого поколения, а на уровне технологий какого-нибудь Эппл М1 уже становится не крайней натяжкой, а вполне рабочей лошадкой. Но только вот в такой вот предельно оптимизированной форме.

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

>Без какого-то продвинутого шедулера
Шедулер тут ничем не поможет, он не в состоянии изменить состояние блоков, только раздать им задачи. Состояние блоков устанавливается драйвером, в соответствии с перестройкой всей BVH.
Он же вполне способен отбалансировать нагрузку.

> Всего в 2 раза быстрее по latency при той же обвязке. На транзисторах, казалось бы, можно выиграть больше, но, при сравнении с вариантом "переиспользовать ALU стандартных шейдеров", все становится не так однозначно. Тем более, нет особой разницы, будет ли оно считать 5 или 50 тактов, если все равно сначала надо ждать данных треугольника из памяти по 500 тактов.
Нет. Нет. Нет. Нет.
Я это всё уже детально расписывал, больше не буду.

#115
4:52, 30 янв 2022

Mobile Developer
> У них есть SIMD для выполнения отдельных векторных команд и только.
У них вся архитектура основана на SIMD: вершины обрабатываются пачками, пиксели обрабатываются пачками, треды обрабатываются варпами. У них есть скалярные команды для реализации ветвлений, но и только. И это неудивительно, ибо простейший способ нарастить флопсы — это сделать ALU толще, без принципиального усложнения остальной обвязки.

> Этот тезис - очень и очень сильное утрирование. Воспринимаю его как ложный. Много места занимают всякие кеши, да. Но в целом нет.
Ну, давай посчитаем: половину кристалла занимает кеш L3, половину оставшегося — L2, половину остатка — L1, в оставшемся куске — половина — регистровый файл, а на оставшиеся капли приходятся, помимо ALU, всякие шедулеры, очереди и прочая вспомогательная обвязка. В общем, примерно 5% и выходит, причем все это хорошо видно на микрофотографиях кристаллов.

> Траверсинг лучей это крайне затратная процедура.
А затратная она потому, что это доступ к памяти, причем зависимый (и обрабатывая по 2 ребенка за раз ты цепочку зависимостей только удлиняешь, роняя производительность в несколько раз).

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

> И ничего, она вполне способна обрабатывать сотни миллиардов запросов к текстурам.
Потому что весь SIMD блок тредов лезет в один блок текстуры, которая уже распакованная лежит в L1 кеше.
Раскидай текстурные координаты пошире и получишь просадку на порядок.

> Специализированная железка, по типу предлагаемой, снижает затраты (условно) до 300гигафлоп.
Флопы — это буквально "операции в секунду", никакая железка их снижать, в принципе, не может. Она может исполнять их быстрее, энергоэффективнее, требовать меньше транзисторов, но никак не снижать их число. У тебя представление о процессорах из прошлого века, когда доступ к памяти был за 1 такт и все считали ассемблерные инструкции. Сейчас доступ к памяти на 2–3 порядка медленней вычислений, основная проблема — эффективно перемещать данные по чипу, а не сложность операций. Сейчас такие оверкилл ALU делают с диким перерасходом транзисторов, и все равно они занимают незначительную площадь чипа.

> Попытка расшарить всю память - автоматически просадит производительность в лучшем случае раз в 10
Latency просадит, а не throughput. А конфликты памяти гораздо дешевле эквивалентных им конфликтов исполнительных устройств.

> Я это всё уже детально расписывал, больше не буду.
Пока я вижу только глубокое непонимание принципов работы современного железа.

#116
13:14, 30 янв 2022

давайте практические примеры - теоретики :)

Страницы: 13 4 5 6 7 8
ПрограммированиеФорумГрафика