Pull to refresh
17
0
Денис Тулупов @viruseg

_

Send message

Попробуйте добавить атрибут [SkipLocalsInit], чтобы избежать постоянной инициализации нулями span'ов. Должно стать быстрее.

Большей части населения РФ требуется не только игра, но и её перевод на русский язык. После ввода ограничений количество игр на русском языке будет стремиться к нулю.

Вспомнил, что в c# есть Span<T>.Fill. Для C использовал компилятор clang-19.1.0 с аргументом "-O3". Результат, абсолютно одинаковая скорость. Так что выводы в статье абсолютно неверные, как и код для тестирования.

Похоже что так и есть. Chatgpt говорит, что: memset относится к языку C как часть стандартной библиотеки, но её оптимизация зависит от компилятора и библиотеки, связанной с ОС.

Без SIMD такой буст как в тестах в статье просто невозможен.

Отметил на скрине avx инструкции.

Можно здесь посмотреть. https://sharplab.io/

Ваш код проверил, цифры те же +- что и у обычного массива.

Насчёт этого не понял. Этот код с Vector256 ну просто не может быть по скорости таким же как как ваш из статьи.

upd: не заметил, что вы написали в комментарии скомпилированный код C, а не c#. На C я не работал. Поэтому подумал, что там есть SIMD инструкции после компиляции и не проверил свою гипотезу.

Не стал упоминать Vector512 иначе бы пришлось этот маленький пример превратить в простыню из:

if (Vector512.IsHardwareAccelerated) {}
else if (Vector256.IsHardwareAccelerated) {}
else if (Vector128.IsHardwareAccelerated) {}
else if (Vector64.IsHardwareAccelerated) {}
else {}

Но это всё не имеет значения в контексте этого теста. Да и моё железо не поддерживает Vector512.

Компилятор C активно использует SIMD инструкции. А в вашем коде c# таких инструкций нет. Перепишите код с использованием Vector128/Vector256 и повторите тест. А то как-то нечестно получилось.

unsafe
{
    const int typicalItarationsCount = 10;
    const int arraySize = 1073741824;
    var lineLength = sizeof(Vector256<byte>);
    var linesCount = arraySize / lineLength;
    
    var tmpArray = new byte[arraySize];
    for (var iteration = 0; iteration < typicalItarationsCount; ++iteration)
    {
        var watch = new Stopwatch();
        watch.Start();
        
        fixed (byte* tmpArrayPtr = tmpArray)
            for (long i = 0; i < linesCount; ++i)
            {
                var vector = Vector256.Create((byte) 1);
                vector.Store(tmpArrayPtr + i * lineLength);
            }

        watch.Stop();
        tmpArray = new byte[arraySize];
        Console.WriteLine($"iter={iteration} seq time={watch.ElapsedMilliseconds}");
    }
}

Примерно так это выглядит на моём пк. Цифры не идеальны т.к. в фоне работает много процессов. Я не ставил целью сделать идеальный тест. Лишь хотел показать тенденцию.

Мой код с Vector256
Мой код с Vector256
Код из статьи
Код из статьи

Если сравнивать C и c#, то только так. У меня нет настроенного рабочего окружения под C чтобы проверить разницу с шарпом. Оставляю это для вас.

В превью статьи ещё осталось "капнуть".

Ммм psd на прямую в юнити

На размер билда это никак не влияет. Абсолютно любой формат изображения попадёт в билд как текстура определённого формата, выбранного в зависимости от платформы. Т.е. любой png/psd/jpg будет конвертирован в какой-нибудь BC7. И финальный размер текстуры будет зависеть от настроек импорта, а не от формата исходного изображения.

Ещё PotPlayer отличная штука.

Зачем размещать статью в хабе Unity, если внутри статьи нет ни слова о Unity?

Самым известным является то, что движок Unity использует только один поток обработки информации при работе с процессором. 

Если unity работает только в одном потоке, то как я сделал этот скриншот профайлера, где видно, что загружены все ядра процессора?

Автор статьи вообще знает о юнити хоть что-то кроме домыслов сделанных на основе даже не знаю чего? Вопрос риторический.

За последние годы в unity проделана огромная работа, делающая движок многопоточным. Есть шикарный инструментарий для программистов Job system. Есть компилятор burst который выдаёт производительность в 10-20 раз большую чем il2cpp и сравним по скорости с нативным плюсовым кодом. Нативные библиотеки такие как физика, система частиц, звук используют дополнительные потоки для своих вычислений. В 23 версии появился Awaitable. А использовать родные Thread никто никогда не запрещал. В каждой новой версии юнити появляется всё большее количество апи которые позволяют работать с движком вне основного потока. Но автор с абсолютной уверенностью пишет, что unity это однопоточный движок, который не умеет в мультипоточность. И эта статья заплюсована.

Просто к сведенью. Видеокарта не работает с png от слова совсем. Браузер каждую png распаковывает в битмап. 1024x760 RGBA8 UNorm это 3.0 MB. На некоторых мобильных устройствах размер текстуры будет изменён до квадрата двойки по большей стороне. Т.е. станет 1024x1024 4.0 MB. А сжатая текстура будет весить 0.7 MB в ETC2 и отправляется в память видеокарты как есть. Но сжатые текстуры придётся делать в разных форматах под разные платформы. В идеале этим должен заниматься движок на котором делается игра.

Ваша демка, что на i7-7700, что на Snapdragon 835 при попытке зума уходит в загрузку на 30 секунд. Я, конечно, не эксперт, но с такими таймингами тут оптимизацией даже не пахнет. И там, и там Chrome последней версии.

2-3 фпс при таком масштабе и погрузка около минуты если сдвинуть карту хоть немного.
2-3 фпс при таком масштабе и погрузка около минуты если сдвинуть карту хоть немного.

Только не рассказывайте автору статьи про RaycastCommand в Unity. А то он совсем в депрессию впадёт.

Откуда вообще берутся такие юзеры на хабре. И кто-то плюсует комментарий.

Под рукой в данный момент открытая unity. Создал простейший шейдер, который берет uv координаты и выводит x. Т.е. на выходе линейное изменение от 0 до 1. Но вообще такое даже проверять глупо. Всё равно, что подвергать сомнению высказывание "земля круглая".

Результат
Результат
Шейдер
Шейдер
Скрин того, что лежит в uv. Чтобы не было сомнений.
Скрин того, что лежит в uv. Чтобы не было сомнений.

А вот с гамма-коррекцией:

Результаты тестирования unsafe методов абсолютно неверны, потому что сами методы написаны неправильно. Закрепление объекта внутри цикла так себе идея, fixed нужно вынести на уровень выше.

public unsafe string Unsafe_ReadOnlySpan_NewString()
{
    ReadOnlySpan<char> chars = Content.AsSpan();
    
    fixed (char* baseChar = chars)
        for (int i = 0; i < chars.Length; i++)
        {
            if (baseChar[i] == ' ') baseChar[i] = ',';
        }
    return new string(chars);
}

Структурные буферы поддерживаются на всех платформах и для всех графических апи. Для доступа к ним из вершинного шейдера нужна Shader Mode 5.0 и выше. Единственное исключение это мобильники из низкого ценового сегмента, работающие на OpenGL ES 2.0.

Что можно сделать ещё, чего я не увидел в статье.

  1. Сменить пайплайн с built-in на URP. SRP-batcher даёт очень сильный буст при использовании разных мешей с одинаковым шейдером.

  2. Отказаться от GameObject и использовать CommandBuffer для отрисовки объектов.

  3. Отказаться от хранения данных в текстуре. Эпоха dx9 давно ушла. Используете structured buffer.

  4. Переход на структурные буферы открывает возможность хорошо перепаковать данные. Вместо 4 каналов png по 8 бит, вы можете использовать структуры любой сложности. С помощью квантизации разместить их максимально компактно. По ссылке пример упаковки данных для сетевой передачи, для видеокарты это конечно же не подходит. Упаковать данные можно лишь в пределах одного элемента структуры. Но принцип тот же.

  5. Файлы с данными можно запаковать с помощью Deflate или GZip.

1
23 ...

Information

Rating
Does not participate
Location
Россия
Date of birth
Registered
Activity