cpp-ru / ideas

Идеи по улучшению языка C++ для обсуждения
https://cpp-ru.github.io/proposals
Creative Commons Zero v1.0 Universal
90 stars 0 forks source link

Математическая библиотека для работы с векторами, матрицами и кватернионами с поддержкой simd #409

Open apolukhin opened 3 years ago

apolukhin commented 3 years ago

Перенос предложения: голоса +13, -0 Автор идеи: damir3

Нужна стандартная математическая библиотека для работы с векторами, матрицами и кватернионами.

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

Для библиотеки желательна максимальная совместимость с OpenGL Shading Language в наименовании функций и типов. За основу можно взять библиотеку glm https://glm.g-truc.net или фрейворк simd из XCode https://developer.apple.com/documentation/simd.

apolukhin commented 3 years ago

yndx-antoshkka, 24 февраля 2019, 4:00 Над этой идеей работает новая подгруппа SG19 Machine Learning. Если захотите написать предложение, скажите, я поспрашиваю у них о планах и о том, как лучше всего им помочь.

Vyacheslav Meshkov, 25 февраля 2019, 21:15 yndx-antoshkka, Вот тут без черновиков с их стороны сложно. В каком это состоянии, в каком направлении движется? Насколько это будет близко к тем, кто это использует? Статьи на хабре показывают, что тема имеет весьма узкий охват аудитории.

Поэтому тут буду писать осторожно и со словами лично мне.

Лично мне хотелось бы видеть вариант более близкий к glsl. Хотя при желании имена типов можно заменить через using. Но тем менее, иметь что-то вроде

vec3f u(1.f,0.f,0.f,0.f), v(0.f, 1.f, 0.f, 0.f);

auto w = u ^ v; // cross-product, w = 0.f, 0.f, 1.f, 0.f

vec4 v(...);

auto w = v.wzyx(); // shufps xmm0, xmm1, 0b00011011

float t = w.get<0>(); // movss DWORD PTR [t], 0

vec4 p = mtx4::rotation(90.f, 1.f, 0.f, 0.f) * vec4(1.f, 0.f, 0.f, 1.f);

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

В общем, в плане простоты финального кода, хотелось бы получить что-то на уровне: https://habr.com/ru/post/418247. Хотя здесь в демонстративных целях было использовано введение глобальных функций, а вообще следует делать через классы.

Но с точки зрения кода, не имеющего узкой графической специализации, к этому коду куча вопросов, когда не до конца ясно надо ли вводить point4 (w=1.f) в дополнении к вектору? А как в конце концов должны размещаться компоненты в регистре: xyzw, wzyx? В каком формате должна храниться матрица? И тем более насколько общими должны быть классы? Плюс требуется поддерживать разные форматы simd данных на разном железе.

В итоге, есть предположение, что до конца непонятно. Реализовывать классы специализированные классы вектора, матрицы, кватернионов, которые всех точно не удовлетворят. Или всё-таки реализовать промежуточные simd классы с функционалом общего назначения (class xmm, с прямыми железными операциями +, -, *, /, shuffle, and, or и прочими), а уже через них реализовать специализированные классы вектора, матрицы и другие. И тогда если кому-то специализированные классы по разным причинам будут неудобны, они смогут их сами реализовать через промежуточные классы. В любом случае необходимость создавать новые классы будет.

Ну и в финале. Есть мысль, что с разными наборами simd инструций тоже всё непросто. На той же x86 есть sse1-3, ssse3, sse4.1, sse4.2, avx, avx2. И уже одна реализация никак не может устроить всех. Делаем вектор на sse1, и тогда теряем преимущества более новых инструций. Делаем на более новых, терям поддержку на старом железе. И вот уже получается неплохо бы иметь

namespace sse {

struct alignas(16) vec4 {

  //...

  vec4 mad(vec4 const& u, vec4 const& v) const { return _mm_add_ps(_mm_mul_ps(fmm, u.fmm), v.fmm); }

};

};

namespace fma {

struct vec4 : sse::vec4 {

  template <typename... Args> vec4(Args&&... args) : avx::vec4(std::forward<Args>(args)...) {}

  vec4 mad(vec4 const& u, vec4 const& v) const { return _mm_fmadd_ps(fmm, u.fmm, v.fmm); }

};

Vyacheslav Meshkov, 25 февраля 2019, 21:57 Под общими классами имел ввиду всё таки не class xmm, а float4, float4x2 (именно так, потому что ближе к логие работы avx), double2, double4. Для других архитектур набор классов может отличаться). Да и по поводу float/double тоже вопрос. Лучше так, или неплохо бы как с интами уже перейти на float32, float64, float80.

WPMGPRoSToTeMa, 26 февраля 2019, 20:30 yndx-antoshkka, речь случаем не о библиотеке для линейной алгебры? Она вроде изначально зародилась из пропозала о 2D-графике?

neondev9, 25 февраля 2019, 0:24 С одной стороны предложение толковое, ибо у каждого есть своя пачка тех же векторов, а это не очень хорошо. С другой стороны, здесь ооочень тяжело будет угодить всем и сразу.

yeputons commented 3 years ago

Кажется, этим активно занимается Guy Davidson? Делал доклады на последних C++ Russia.

https://www.youtube.com/watch?v=hPlEN_UtJSI

AKonia commented 3 years ago

Идея хорошая, но если ничего не путаю, то MSVC-DirectX фанаты не сразу заценят, вернее т.к. в DirectX система координат левосторонняя, а в opengl правосторонняя, скорее всего выйдет спорная библиотека, т.к. тут либо опционально устанавливать систему координат, либо получить неодобрение от двух лагерей игровых разработчиков. Плюс напомню, что в gccшных расширениях было что-то подобное.