На сколько я понял, номер шарда у них, это аналог версии баннера, а дальше делается просто CAS или Test And Set, как у многих атомарных операций - параллельно два обработчика меняют данные одно и того же баннера, но закоммитить изменения сможет только один из них, т.к. коммит выполнится только при условии, что версия баннера в базе совпадает с ожидаемой. Второй же обработчик увидит новый номер версии, проставленный первым, транзакция не пройдет и ему придется заново читать изменения из базы и снова пытаться повторить свои изменения.
Ах если бы всё было так просто и можно было весь пайп-лайн прибить гвоздями. На практике, иногда нет аппаратного декодера или энкодера. Конфигурация определяется динамически и код обязан работать корректно. Аппаратура не совершенна и многие карты захвата не могут класть данные напрямую в GPU. Даже если энкодер аппаратный, нам приходится приходится правильно передавать данные из CPU в GPU.
Тема действительно интересная, обширная и сложная. Если брать изображения вообще в общем, как буфер кадра который может прийти откуда угодно, с любой аппаратной части, находится в разного типа памяти, то например в ffmpeg или библиотеках обработки видео и изображений всё становиться еще сложнее. Там у буфера кадра одновременно присутствует и align, и такие понятия как pitch и stride, причем все они могут иметь разные значения в общем случае: align - это выравнивание начала строки в байтах. Необходимо для того, что бы строка могла быть обработана SIMD инструкциями, которые требуют выравнивания. pitch - это выравнивания в пикселах (может быть горизонтальным и вертикальным). Необходимо тем или иным алгоритмам, которые работают блоками, например кодеки или специфические фильтры. stride - это выравнивание строки в байтах. Необходимо как для работы SIMD, так и для менеджера памяти, который используется для хранения изображения (например в видеопамяти). Также в зависимости от формата изображения могут иметь так называемые плоскости (цветовые компоненты), которые хранятся отдельно друг от друга и имеют собственные выравнивания. На практике всё это может быть не кратно друг другу, а каждый кодек имеет свои значения. В своё время пришлось плотно разбираться с этим и разрабатывать хитрые обертки, что бы сделать прозрачную передачу (без копирования): кадр из оперативной памяти -> медиа семпл DirectShow -> ffmpeg кадр -> медиа семпл DirectShow -> кадр в оперативной памяти
Да, тоже становится грустно, почему люди не проверяют факты, которые сами же вскользь и указывают: Wolf 3D - ray casting и DDA, ускорение относительно честного 3D происходит из-за того, что все расчеты происходят на 2-мерной карте, разделённой на прямоугольные блоки одинакового размера. Стены могут быть только кратны определённой сетке и вертикальными. Duke Nukem 3D - portals, ускорение относительно честного 3D происходит за счет того, что отсечение происходит на 2-х мерной карте пошагово, от ближнего портала (выпуклое множество полигонов), потом следующие порталы, те, что потенциально могут быть видны из текущего и т.д. В отличие от BSP, все расчеты происходят в реальном времени, соответственно карта игры большими частями может меняться динамически. Doom - BSP, ускорение относительно честного 3D происходит за счет того, что стационарные стены рисуются по порядку, от ближних к дальним по специальному дереву, опять же на 2-мерной карте. Стены также строго вертикальные, но уже под любым углом по оставшимся плоскостям. Quake - честный 3D, но стационарные стены рисуются по 3-х мерному BSP на 3-х мерной карте. Отсюда ограничения, большая часть мира - статическая, т.к. BSP очень дорого рассчитывать в динамике.
Итого, из основных родоначальников жанра, только Wolf 3D использует ray casting.
в UTF-16 кодовая точка всегда использует 2 байта (16 бит)
И тут же противоречие:
Но максимальным значение 16-битного числа является 65535! Как представляются большие числа в UTF-16? Для этого используется концепция суррогатной пары (surrogate pair)
Вывод: В UTF-16 кодовая точка, также как и в UTF-8, занимает максимум 4 байта.
Моё замечание относится к тому, что хотя в общем идея чисел с плавающей точкой объяснена, только вот в IEEE-754 экспонента (e) - это показатель степени по основанию 2, а не по основанию 10, как в статье. Т.е. не 10^e, а 2^e.
Мне кажется, что в современном С++ это можно сделать на уровне библиотеки и работать с такими числами почти как с встроенными. Вот моя попытка написать такое для целых - Simple long integer math library for C++. Посмотрите, может подойдет. Из того, что вам нужно, там нет точности до бита и динамического изменения размера, так как я пока не знаю как выполнить эти требования и при этом быть сравнимым по эффективности с встроенными типами.
constexpr auto uo = 03766713523035452062041773345651416625031020_ui128; // octal unsigned integer
constexpr auto ud = 338770000845734292534325025077361652240_ui128; // decimal unsigned integer
constexpr auto uh = 0xfedcba9876543210fedcba9876543210_ui128; // hexadecimal unsigned integer
constexpr auto io = -03766713523035452062041773345651416625031020_si128; // octal signed integer
constexpr auto id = -338770000845734292534325025077361652240_si128; // decimal signed integer
constexpr auto ih = -0xfedcba9876543210fedcba9876543210_si128; // hexadecimal signed integer
constexpr auto u = 0xfedcba98'76543210'fedcba98'76543210_ui128; // hexadecimal unsigned integer
Ну я как-раз про это и говорю, откуда слухи - от не разобравшихся преподов. Увидели слово pascal - значит паскаль, однозначно! PASCAL тут - это define __stdcall
Да, всё верно. Тип вызова pascal отличается от stdcall противоположным порядком проталкивания аргументов. Я не хотел вдаваться в дебри различных типов вызовов, тем более, что сейчас в x64 многие из них уже не актуальны и унифицированы. Я лишь хотел этим проиллюстрировать откуда могли взяться слухи, что Windows писался на Pascal-е и что разработчикам на конференции задавали уже этот вопрос. Ответ был - Windows писался на С.
Windows писался на С. Единственное, что там могло быть от языка Pascal, тип вызова функций - pascal (когда стек зачищает сама вызываемая функция). Так отвечали на этот вопрос сами разработчики, которых спрашивали когда они приезжали на конференцию по Windows, 20 лет назад.
Я за Open Source, но от выводов в статье остаётся ощущение недосказанности. Логика подсказывает, что коммерческая компания не просто так тратит такую уйму сил и не просто для того, что бы поделиться своими наработками с сообществом. Я хотел бы ошибаться, но мне кажется, что на самом деле здесь больше решаются юридические тонкости и основная цель - защитить те или иные российские разработки от нападок извне или наоборот, а Open Source это только форма. Опять же, не вижу в этом ничего плохого, думаю так многие компании делают, но если это действительно так, то всё встает на своё место.
Вроде фильтры совсем базовые и простые но есть одно замечание и один совет. Замечание - gamma у вас работает неправильно. В нем граничные значения динамического диапазона [0, 255] (или [0.0, 1.0], если удобно) должны переходить сами в себя. Поэтому лучше сначала отнормировать значение яркости к [0.0, 1.0], а потом уже возводит в степень, затем обратно. Совет - так как фильтры точечные и каждый канал обрабатывается независимо, лучше считать их в таблице для всех значений динамического диапазона, [0, 255] например, и уже потом брать оттуда. Во-первых, это сделает скорость любого фильтра независимой от размера изображения и от сложности самого фильтра. Во-вторых, можно применять сразу несколько фильтров к таблице, а потом обсчитывать уже каналы изображения по ней. Это еще увеличит скорость обработки.
Современные процессоры устроены совсем не так, как в 80-х. Здесь, мне кажется, нужны замеры - насколько это медленнее. Нельзя же производительность в этом случае линейно, по количеству команд, мерить.
Отсутствие флагов это не убогость, а преимущество. Все современные архитектуры отказываются от флагов, т.к. это лишнее глобальное состояние, из-за которого в конвейере процессора даже не зависимые по данным команды начинают зависеть друг от друга, а это очень сильно мешает распараллеливанию выполнения.
Это будет в два раза медленнее, чем это возможно. Зачем так делать? Я с трудом представляю архитектуру, где не было бы adc, но даже, если это так, то перенос легко вычислить для полной суммы:
Он и так это без костылей оптимизирует: adc, sbb всякие, simd где может использует. О каких костылях речь ? На 32-х битной архитектуре 64-х битные целочисленные операции (long int) уже через вызовы отдельных функции выполняются, а как иначе, это костыли?
На сколько я понял, номер шарда у них, это аналог версии баннера, а дальше делается просто CAS или Test And Set, как у многих атомарных операций - параллельно два обработчика меняют данные одно и того же баннера, но закоммитить изменения сможет только один из них, т.к. коммит выполнится только при условии, что версия баннера в базе совпадает с ожидаемой. Второй же обработчик увидит новый номер версии, проставленный первым, транзакция не пройдет и ему придется заново читать изменения из базы и снова пытаться повторить свои изменения.
Ах если бы всё было так просто и можно было весь пайп-лайн прибить гвоздями. На практике, иногда нет аппаратного декодера или энкодера. Конфигурация определяется динамически и код обязан работать корректно. Аппаратура не совершенна и многие карты захвата не могут класть данные напрямую в GPU. Даже если энкодер аппаратный, нам приходится приходится правильно передавать данные из CPU в GPU.
Тема действительно интересная, обширная и сложная. Если брать изображения вообще в общем, как буфер кадра который может прийти откуда угодно, с любой аппаратной части, находится в разного типа памяти, то например в ffmpeg или библиотеках обработки видео и изображений всё становиться еще сложнее. Там у буфера кадра одновременно присутствует и align, и такие понятия как pitch и stride, причем все они могут иметь разные значения в общем случае:
align - это выравнивание начала строки в байтах. Необходимо для того, что бы строка могла быть обработана SIMD инструкциями, которые требуют выравнивания.
pitch - это выравнивания в пикселах (может быть горизонтальным и вертикальным). Необходимо тем или иным алгоритмам, которые работают блоками, например кодеки или специфические фильтры.
stride - это выравнивание строки в байтах. Необходимо как для работы SIMD, так и для менеджера памяти, который используется для хранения изображения (например в видеопамяти).
Также в зависимости от формата изображения могут иметь так называемые плоскости (цветовые компоненты), которые хранятся отдельно друг от друга и имеют собственные выравнивания. На практике всё это может быть не кратно друг другу, а каждый кодек имеет свои значения. В своё время пришлось плотно разбираться с этим и разрабатывать хитрые обертки, что бы сделать прозрачную передачу (без копирования):
кадр из оперативной памяти -> медиа семпл DirectShow -> ffmpeg кадр -> медиа семпл DirectShow -> кадр в оперативной памяти
Да, тоже становится грустно, почему люди не проверяют факты, которые сами же вскользь и указывают:
Wolf 3D - ray casting и DDA, ускорение относительно честного 3D происходит из-за того, что все расчеты происходят на 2-мерной карте, разделённой на прямоугольные блоки одинакового размера. Стены могут быть только кратны определённой сетке и вертикальными.
Duke Nukem 3D - portals, ускорение относительно честного 3D происходит за счет того, что отсечение происходит на 2-х мерной карте пошагово, от ближнего портала (выпуклое множество полигонов), потом следующие порталы, те, что потенциально могут быть видны из текущего и т.д. В отличие от BSP, все расчеты происходят в реальном времени, соответственно карта игры большими частями может меняться динамически.
Doom - BSP, ускорение относительно честного 3D происходит за счет того, что стационарные стены рисуются по порядку, от ближних к дальним по специальному дереву, опять же на 2-мерной карте. Стены также строго вертикальные, но уже под любым углом по оставшимся плоскостям.
Quake - честный 3D, но стационарные стены рисуются по 3-х мерному BSP на 3-х мерной карте. Отсюда ограничения, большая часть мира - статическая, т.к. BSP очень дорого рассчитывать в динамике.
Итого, из основных родоначальников жанра, только Wolf 3D использует ray casting.
Цитата:
И тут же противоречие:
Вывод: В UTF-16 кодовая точка, также как и в UTF-8, занимает максимум 4 байта.
Моё замечание относится к тому, что хотя в общем идея чисел с плавающей точкой объяснена, только вот в IEEE-754 экспонента (e) - это показатель степени по основанию 2, а не по основанию 10, как в статье. Т.е. не 10^e, а 2^e.
10 - или я не понял вопроса ?!
Всё хорошо в объяснении, только вот экспонента (порядок) это степень двойки, а не десятки. Неплохо бы было объяснить и это момент.
Мне кажется, что в современном С++ это можно сделать на уровне библиотеки и работать с такими числами почти как с встроенными. Вот моя попытка написать такое для целых - Simple long integer math library for C++. Посмотрите, может подойдет.
Из того, что вам нужно, там нет точности до бита и динамического изменения размера, так как я пока не знаю как выполнить эти требования и при этом быть сравнимым по эффективности с встроенными типами.
Так ведь _pascal calling conversion давно уже устарело и не рекомендуется к использованию. Это смотря где определение.
https://learn.microsoft.com/en-us/cpp/cpp/obsolete-calling-conventions?view=msvc-170
В общем это всё дела уже минувших дней и неактуально сегодня.
Ну я как-раз про это и говорю, откуда слухи - от не разобравшихся преподов. Увидели слово pascal - значит паскаль, однозначно!
PASCAL тут - это define __stdcall
Да, всё верно. Тип вызова pascal отличается от stdcall противоположным порядком проталкивания аргументов. Я не хотел вдаваться в дебри различных типов вызовов, тем более, что сейчас в x64 многие из них уже не актуальны и унифицированы. Я лишь хотел этим проиллюстрировать откуда могли взяться слухи, что Windows писался на Pascal-е и что разработчикам на конференции задавали уже этот вопрос. Ответ был - Windows писался на С.
Windows писался на С. Единственное, что там могло быть от языка Pascal, тип вызова функций - pascal (когда стек зачищает сама вызываемая функция). Так отвечали на этот вопрос сами разработчики, которых спрашивали когда они приезжали на конференцию по Windows, 20 лет назад.
Я за Open Source, но от выводов в статье остаётся ощущение недосказанности. Логика подсказывает, что коммерческая компания не просто так тратит такую уйму сил и не просто для того, что бы поделиться своими наработками с сообществом. Я хотел бы ошибаться, но мне кажется, что на самом деле здесь больше решаются юридические тонкости и основная цель - защитить те или иные российские разработки от нападок извне или наоборот, а Open Source это только форма. Опять же, не вижу в этом ничего плохого, думаю так многие компании делают, но если это действительно так, то всё встает на своё место.
Вроде фильтры совсем базовые и простые но есть одно замечание и один совет.
Замечание - gamma у вас работает неправильно. В нем граничные значения динамического диапазона [0, 255] (или [0.0, 1.0], если удобно) должны переходить сами в себя. Поэтому лучше сначала отнормировать значение яркости к [0.0, 1.0], а потом уже возводит в степень, затем обратно.
Совет - так как фильтры точечные и каждый канал обрабатывается независимо, лучше считать их в таблице для всех значений динамического диапазона, [0, 255] например, и уже потом брать оттуда. Во-первых, это сделает скорость любого фильтра независимой от размера изображения и от сложности самого фильтра. Во-вторых, можно применять сразу несколько фильтров к таблице, а потом обсчитывать уже каналы изображения по ней. Это еще увеличит скорость обработки.
Современные процессоры устроены совсем не так, как в 80-х. Здесь, мне кажется, нужны замеры - насколько это медленнее. Нельзя же производительность в этом случае линейно, по количеству команд, мерить.
Отсутствие флагов это не убогость, а преимущество. Все современные архитектуры отказываются от флагов, т.к. это лишнее глобальное состояние, из-за которого в конвейере процессора даже не зависимые по данным команды начинают зависеть друг от друга, а это очень сильно мешает распараллеливанию выполнения.
В любом случае, если в архитектуре нет команды adc, то будут накладные расходы, но не большие.
Вот например выхлоп для RISC-V:
Выглядит очень не плохо, на мой взгляд.
Это будет в два раза медленнее, чем это возможно. Зачем так делать? Я с трудом представляю архитектуру, где не было бы adc, но даже, если это так, то перенос легко вычислить для полной суммы:
Он и так это без костылей оптимизирует: adc, sbb всякие, simd где может использует. О каких костылях речь ? На 32-х битной архитектуре 64-х битные целочисленные операции (long int) уже через вызовы отдельных функции выполняются, а как иначе, это костыли?