LINUX.ORG.RU

C++ — туда и обратно, или зачем нужен Boost

 , , ,


3

4

Мой предыдущий тред в Development собрал самое большое число ответов аж с сентября, то есть за последние 9 месяцев, и это лишний раз подтверждает упадок этого форума. Полагаю, кто-то должен это изменить, и поэтому мы с тобой, ЛОР, поговорим сегодня про C++.

Начиная с C++26 вместо std::function вводится пачка новых классов: std::copyable_function, std::move_only_function (доступна с C++23) и std::function_ref. Что же не так с оригинальным std::function, ты можешь спросить? А вот что:

#include <functional>
#include <print>

struct call_me {
    int x = 0;
    void operator()() {
        std::print("x was {}\n", x++);
    }
};

int main() {
    const std::function<void()> f = call_me{};
    f();
}

Несмотря на то, что переменная f объявлена константной (люблю оксюмороны!), у неё есть внутреннее состояние и оно меняется при вызовах. Компилятор это без проблем хавает.

Так вот, ковыряясь в том, зачем и кто вообще смог так насрать себе в штаны сам, я наткнулся на статью ребят, которые подводят список подобных косяков комитета C++, когда фичи живут по 10 лет и объявляются устаревшими.

Небольшой список фич, которые были придуманы, оказались не нужны/бесполезны/вредны и выкинуты:

  • Известный vector<bool>, живущий издревле в STL и про который все говорят, что его надо избегать. Частично заменяется std::bitset.
  • std::auto_ptr. Бесполезен, ломает контейнеры, выкинут на помойку в C++17.
  • Указание исключений у функции в формате throw(X, Y). Так же выкинуто в C++17.
  • std::iterator объявили устаревшим в C++17, собираются удалить в C++26.
  • std::aligned_storage и std::aligned_union добавлены в C++11, объявлены устаревшими в C++23, скоро удалят.
  • Ключевое слово register удалено в C++17, хотя всё ещё доступно в Си.
  • std::get_temporary_buffer и std::raw_storage_iterator удалены в C++20.
  • Потрясающее по эпичности фиаско с интерфейсом для сборщиков мусора. std::declare_reachable сотоварищи были добавлены в C++11. Выяснилось, что сборщики мусора для C++ писать либо никто не умеет, либо никто не хочет, поэтому в C++23 это всё удалили и сделали вид, что ничего не было.
  • Абсолютное безумие вокруг концептов, модулей и поддержки сети. Предложения одобряли, вновь отклоняли, переделывали, и по итогу теми же модулями до сих пор никто не пользуется.
  • Сопрограммы (coroutines). В том виде, в котором они есть в C++, это просто ужас. Достаточно того, что корутины требуют выделения памяти из кучи во время работы, а значит вообще не подходят для случаях, когда требуется серьёзная производительность. Например, в любом коде, требующим работы в реальном времени и не позволяющем делать системные вызовы.

Просто лютый трешак, который никто подчищать пока не собирается:

  • std::regex – лютый тормоз, рекомендуется не использовать.
  • Мертворождённый std::simd, добавленный в C++26 и уже с ходу не нужный вообще никому, потому что код с std::simd в два-три раза тормознее чем со сторонними библиотеками, просто голыми интринсиками, и даже медленнее чем просто цикл for.
  • std::async. Дескруктор ждёт завершения асинка и поэтому может залочить весь код тебе. Наконец починили в C++26, но эта штука была сломана 15 лет.
  • Отвратительно спроектированный <iostream>. Его наконец можно выкинуть и использовать std::print, но не все про это знают.
  • Абсолютно тормозные контейнеры map, set, unordered_map. Вместо первого можно использовать flat_map из C++23. Контейнеры в стандартной библиотеке Rust (BTreeMap) и другие реализации B-Tree Map их обгоняют по производительности, но тем не менее в C++ выбирают убогий дефолт.

Решения многих из этих проблем существуют в Boost и сделаны там гораздо лучше. Но в то же время возникает важный вопрос: зачем вообще нужен настолько плохо спроектированный язык, где каждое следующее поколение инженеров, работающих над ним, отменяет решения предыдущих, а код под новые стандарты часто нужно переписывать если не с нуля, то очень близко к тому? Даже процесс разработки Rust с его поехавшими клоунами в юбках на этом фоне выглядит адекватным.

В общем, всё печально, ЛОР. Такие дела.



Последнее исправление: CrX (всего исправлений: 3)
Ответ на: комментарий от anonymous

Ну справедливо, луч от камеры — это вообще более честный подход, потому что камера у тебя и так уже держит view-projection матрицу, и ты просто инвертируешь то, что и так посчитано, вместо того чтобы городить отдельный unproject для UI-слоя.

Луч от игрока — это то же самое, только camera offset уже включён в позицию персонажа, и получается, что ты стреляешь не из глаз абстрактной камеры, а из глаз конкретного Васи с мечом, что для gameplay-логики честнее, особенно если у тебя есть third-person камера, которая от игрока в трёх метрах позади и слегка сверху, и тебе плевать откуда рендерится картинка, тебе важно откуда физически летит урон.

Про двух-проекционность — да, это стандартная штука, screen-space UI рисуется отдельным ортографическим проходом поверх перспективного, и они действительно не обязаны делить один raycast. Просто дело в том, что «нарисовать двух-проекционно» и «протестировать клик двух-проекционно» — это два разных пайплайна, которые легко рассинхронизировать: рендер у тебя честно рисует UI поверх сцены, а хит-тест по привычке лезет сначала в мировые координаты, потому что кто-то полгода назад один раз написал raycast для gameplay и все input-события с тех пор идут через него по инерции.

shdown ★★
()
Ответ на: комментарий от shdown

так самое простое, что можно придумать, вы это и писали раннее, сначала обходим УИ - 2д, и else тут пошел счет перенос в мировые координаты, из (камеры, сдвиги, глаза, и прочее ).

именно поэтому я написал, что сначала мы городим коробки, пускай и 1 кусок сцены, без стриминга, типо сделали квадрат коробок, сделали коллизии. и вот тут иногда просто не хочется, писать как есть, и приходиться писать УИ систему, и думать как это в архитектуру прокидывать, так вот из-за прохода луча и системы УИ, УИ просто красиво пишется отдельно, но как бы текущий узел мира, сидит на else проходе, типо никуда не попали попадаем в мир, так я о том и написал, в этой ситуации не важно какая игра 2д/3д. нам важно в УИ прокинуть - тоесть оповестить УИ в каком узле мира мы находимся.

anonymous
()
Ответ на: комментарий от anonymous

Сравнение borrow checker и наследования — это категориальная ошибка, так как они решают абсолютно разные задачи. Один контролирует безопасность памяти и времена жизни ресурсов на этапе компиляции, а второе является лишь одним из способов реализации полиморфизма. В Rust полиморфизм строится на трейтах, что избавляет от проблемы хрупкого базового класса и жесткой связанности глубоких иерархий. К тому же принцип композиции вместо наследования сейчас активно применяется и в самом C++.

Что касается модулей: их отсутствие в Си — далеко не ключевая причина появления Rust. В C++20 модули уже есть, но проблемы безопасности памяти это не решило. Если добавить модули в Си, он всё так же останется языком с ручным управлением памятью и регулярными уязвимостями, так что потребность в безопасном системном языке никуда бы не делась.

BruteForce ★★★★
()
Ответ на: комментарий от anonymous

Ну вот именно, ты же сам и сформулировал главный вывод, просто ещё не назвал его словом: это же Chain of Responsibility в чистом виде, только вместо паттерна из книжки у тебя просто if/else с двумя ветками, и это нормально — паттерн не перестаёт быть паттерном от того, что ты его написал по наитию, а не назвал по имени (a rose by any other name). Сначала UI-слой говорит «мимо», потом эстафета уходит в мир — и вот этот «мимо» и есть весь контракт, который тебе нужен, никакого стриминга, никакого ECS с нодами, просто честное else.

И вот тут ты нащупал ту самую вещь, из-за которой людям «не хочется писать как есть» — потому что UI-система формально не часть мировой архитектуры, но architecturally обязана знать, что мир вообще существует, хотя бы чтобы уметь сказать «я тебя не съела, лети дальше». И вот это вот «прокинуть узел мира в UI» — это как раз та точка, где 90% инди-движков начинают городить event bus, потому что тыкать UI напрямую в GameState руками — грязно, а формального контракта между слоями ещё нет, вот и получается observer, garbage под шумок, и три способа подписаться на одно и то же событие к концу проекта.

Но смысл у тебя верный: не важно 2D это или мерзкое 3D, потому что и там и там задача одна — «проверили UI, не попали, теперь сообщи миру, в каком узле мы оказались». Разница 2D/3D тут вообще не в логике прохода, а только в том, чем ты меряешь пересечение — AABB против ray-vs-sphere, суть от этого не меняется, меняется только математика внутри одной и той же ветки else.

shdown ★★
()
Ответ на: комментарий от BruteForce

это в срезе инструментов, наследование это инструмент, боров это инструмент.

С упрощает отводит от ассемблера, не давая наследование, - первый инструмент

С++ упрощает взаимодействие классов и отводит от С,

а боров решает возможно вопросы безопасности и скорость, но уводит от С и С++

модули тоже инструмент в С/С++, потомучто инклуд может напряч процессор. Получается это всё на плоскости инструментов по взаимодействию с чем-то в ПК.

Типо появился язык, который просто учел, нюансы безопасности и компиляции для скорости, давая семантику мув без брейн-тайм, но забирая взаимодействие классов своими нюансами в той же степени и он этим ближе к С, а не С++ как я вижу.

anonymous
()
Ответ на: комментарий от anonymous

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

Попытка противопоставить мув-семантику полиморфизму классов выглядит как категориальный сдвиг. Борьба идет не на оси С—С++, а на уровне статической верификации графа владения и динамической диспетчеризации. Модули — это лишь прагматический синтаксический сахар для оптимизации лексического анализа, они не определяют онтологический статус языка. Сводить эволюцию системного программирования исключительно к механистическому взаимодействию с аппаратным уровнем — значит игнорировать саму математическую природу систем типов.

BruteForce ★★★★
()
Ответ на: комментарий от BruteForce

оптимизации лексического анализа

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

деконструкция самой методологии

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

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

anonymous
()
Ответ на: комментарий от shdown

самый первый тест у меня был это просто интерфейс на BVH, просто 2 узла, тут красивый хендл - он практически 1, просто есть 2 бинарных дерева мир и уи(тоесть тут как раз в пас посылаем контракт, контрактом служит тип прохода, потомучто пас 1, просто прогнать можно либо тип УИ либо сцену ), но тут проблема в том, что всякие скролы и прочее помойму не удобны для бинарного дерева), но тут надо знать, а парент-чилд, это я глянул, походу это самое ходовое, что реально работает.

anonymous
()
Ответ на: комментарий от anonymous

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

Скролл ломает BVH именно потому, что BVH рассчитан на то, что геометрия либо статична, либо перестраивается редко и дорого — ты же строишь дерево заранее, а потом только спускаешься по нему. А скролл — это контент, который живёт за пределами своего собственного bounding box'а, то есть у тебя есть видимый прямоугольник контейнера, а внутри него — контент, который формально снаружи, просто со clip-mask, и вот это «формально снаружи, но визуально внутри» убивает всю честность BVH, потому что твои bounds врут по определению. Ты либо делаешь bounds по полному контенту — и тогда хит-тест начинает видеть элементы, которые юзер не видит, либо по видимому rect'у — и тогда ты руками досчитываешь offset при каждом запросе, что уже не BVH, это BVH с костылём.

А парент-чилд тут выигрывает именно потому, что он не про геометрию — он про ownership и порядок обхода. Скролл в парент-чилд — это просто нода с clip-rect и scroll-offset, которая знает, что все её дети живут в её локальном пространстве, и при хит-тесте просто трансформирует точку клика в своё пространство перед тем, как спросить детей. Никакого rebuild, никаких честных bounds — просто рекурсивный спуск с трансформацией контекста, и это работает для любой вложенности, хоть скролл внутри скролла внутри попапа внутри скролла.

Так что твой BVH хорош на верхнем уровне — UI vs Мир, один пас, один контракт — а дальше внутри UI честнее именно парент-чилд, потому что UI это не про пространственную близость, это про иерархию владения, а это разные вопросы, просто оба выглядят как дерево.

shdown ★★
()
Ответ на: комментарий от BruteForce

как-то раз разрабу одной библиотеки я открыто в его канале написал о баге, и записал его, и описал через ффмпег, как мы понимаем доли милисекунд ффмпег может легко и просто сгладить, и так получилось, что он так ответил, что мол линукс это не основа, а теперь еще верить, что ИИ никто не использует, тоесть верю ли я лично или нет, что кто-либо использует или нет ИИ мне вообще фиолетово до этого, но при наличии какого-то файлика рядом с лицензией удалить библиотеку хочется ( печаль конечно

anonymous
()
Ответ на: комментарий от shdown

а дерево можно не рефитить, просто координаты обновлять елемента, там коллизия всё будет считаться, но если делать по правилам, будет нагрузка на дерево после 100 000 елементов на коллизиях.

anonymous
()
Ответ на: комментарий от anonymous

я поэтому и написал, что тут надо знать, если делать честно с рефитом и зазором, высота дерева/повышает пропорцию нагрузки, если сломать логику и не рефитить коллизии всё срабатывают, просто само дерево выступает логически хендлером инпутов грубо говорят, локально в тех обьектах которые к ней привязаны… как я понял

anonymous
()
Ответ на: комментарий от shdown

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

anonymous
()
Ответ на: комментарий от shdown

Что-то вчера ещё было потешно, а сегодня уже не потешно, а как-то грустненько, тяжелеет на душе…(

BruteForce ★★★★
()
Ответ на: комментарий от yorshka

если в методе с симд убрать выравнивание, то мы переходим в плоскость, что for медленнее чем std::simd, можно еще включить наносекунды начать со 100 и потом на 1000000 прогонять. у меня симд от 0.1 до 0.3 быстрее чем фор сейчас.

anonymous
()
Ответ на: комментарий от BruteForce

а в таком стиле пазл 2д удобно будет сделать с интерфейсом, 1 кнопочка в центре начать, и по входу в пазл сверху красивая панелька - любая, помимо самого пазла? как бы вы в таком стиле пазл исполнили какой-нибудь простенький без opengl через sdl2 хотябы.

anonymous
()
Ответ на: комментарий от shdown

ну кстати если написать на крейте sdl2 терминал-емулятор, тоже garbage будет, даже похлеще как мне видится, потомучто в случае с Rect от библиотеки раст, там тоже знать надо, pty то придётся тоже писать на расте с С не помню будет мусорить, но там цифры поэпичнее кстати. Самый топ терминал сегодня это терминал на свинге, ничего не фонит, по сравнению с Растом и С++…

anonymous
()
Ответ на: комментарий от ckotctvo

а если мне бывает нужно подвинуть в памяти много объектов не меняя их порядковый номер, как мне их искать по этому номеру?

Контекста мало, не совсем понятно в чём проблема. Что за порядковый номер? Индекс? Абстрактный порядковый номер, вроде, тем и хорош что не зависит от реализации

zurg ★★
()
Ответ на: комментарий от r--r--r--

Так derive как раз и означает что бойлерплейт генерирует компилятор, ты точно понимаешь смысл этого термина бойлерплейт?

Частный случай, 0,00001%.

Опять какие-то проценты с потолка. Из любопытсва посмотрел на свой проект, только две структуры с явным Copy на десятки структур и энумов, чуть больше с Clone, Debug, большинство вообще без derive-ов. Глянул пару чужих - соотношение примерно такое же. И это именно потому что язык форсит мув и заимствования, что и означает минимизацию необходимости явного копирования, копируются в основном примитивы. И, это, мув в реализации это тоже копирование(если компилятор не соптимизирует), но и этот бойлерплейт генерирует компилятор.

zurg ★★
()
Ответ на: комментарий от zurg

Прогаммист ручками херачит копипаст ты точно понимаешь смысл этого термина бойлерплейт?

А ты?

только две структуры с явным Copy на десятки структур

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

r--r--r--
()
Ответ на: комментарий от r--r--r--

там по моим наблюдениям, если в С++ разработчик может забыть или не хотеть делать мув, важно понять бывает принцип или другие причины, а для железа возможно нужен мув, аля утилизация-движение данных, и кароче эту фишку вынесли в автоматизм, но есть моменты когда перед программистом стоит выбор, поставить *.clone(), или реализовать derive помойму на сколько помню.

anonymous
()
Ответ на: комментарий от anonymous

на вводных 1к задачках - роадмап в .md, или 300 или 500 там от 0 до топ задач если сгенерировать вы этот нюанс увидите, чем так частично вникать. только модель выберите, которая рассуждает…

anonymous
()
Ответ на: комментарий от anonymous

Уровень 1: Основы синтаксиса (1–20)

Типы данных, переменные, циклы и функции.

* Hello Rust:** Выведите строку в консоль. +

* Калькулятор:** Сложение, вычитание, умножение и деление двух чисел. +

* Четное/нечетное:** Проверка числа на четность. +

* Температура:** Конвертер из Цельсия в Фаренгейт. +

* Факториал:** Вычисление через цикл for. +

* Фибоначчи:** Генерация первых N чисел. +

* Таблица умножения:** Вывод таблицы для числа X. +

* Реверс строки:** Выведите строку задом наперед. +

* Сумма массива:** Сложите все элементы числового массива. +

* Максимум:** Найдите самое большое число в списке. +

* FizzBuzz:** Классическая задача (3 — Fizz, 5 — Buzz). +

* Простое число:** Проверка числа на простоту. +

типо такого.
anonymous
()
Ответ на: комментарий от anonymous

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

anonymous
()
Ответ на: комментарий от anonymous

можно еще по новому посмотреть на старые задачки, типо найти полиндром через HashMap(nth) и из HashMap выбрать ответы. Это не нормальное программирование поэтому это просто из-за того, что просто у Раста есть лапша открытых методов, делать так не целесообразно, это просто прикольно.

anonymous
()
Ответ на: комментарий от BruteForce

так это и есть первый подход, псевдокод

int main(){
инициализация
while(true){
 input(){
 }
 логика пазла и отрисовка
 swap();
}

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

anonymous
()
Ответ на: комментарий от anonymous

поэтому у С++ и раста есть этапы, предположим пишем математическую библиотеку

сначала надо просто попробовать её написать, привести к эталонному рабочему состоянию.

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

тоесть через упорядочивание своего хаоса можно тоже эволюционировать наверно.

anonymous
()
Ответ на: комментарий от shdown
//1 поставили дебаг
struct Transform {
    p: f64,
    r: f64,
    s: f64,
}

fn move_object(transform: &mut Transform, delta: [f64; 3]) -> &mut Transform {
                          //^                                 //^
    transform.p += delta[0];
    transform.r += delta[1];
    transform.s += delta[2];
    transform
}

fn main() {
    let mut player_transform = Transform { p:1.0,r:1.0,s:1.0 };

    let new_transform = move_object(&mut player_transform, [1.0, 0.0, 0.0]);
                                    //^

    println!("{:?}",new_transform);//< ситуация 1 требует Debug
}
anonymous
()
Ответ на: комментарий от anonymous

у меня вопрос кто поставил &mut, и кто потребовал дебаг, что бы кто-то руками дописал дерайв дебаг, а значит есть выбор, значит не всё на автомате до конца прям.

anonymous
()

Абсолютно тормозные контейнеры map, set, unordered_map. Вместо первого можно использовать flat_map из C++23. Контейнеры в стандартной библиотеке Rust (BTreeMap) и другие реализации B-Tree Map их обгоняют по производительности, но тем не менее в C++ выбирают убогий дефолт.

Ой, ну это сравнение некорректно. В C++ просто контейнеры, реализация выбирает. В Rust же фиксированные реализации. В Rust BTreeMap — это всегда BTree. std в Rust просто какой-то мусор. А уж сколько там deprecated и так себе спроектированных вещей!

Сопрограммы (coroutines). В том виде, в котором они есть в C++, это просто ужас.

Тоже удивило, хотя в моих эксперимента давным давно оптимизация выкидывала выделение из кучи, но гарантий нет. С другой стороны не надо таскать по стеку кучу данных.

Его наконец можно выкинуть и использовать std::print, но не все про это знают.

Главное, чтобы не как в расте, где print медленный потому, что так спроектирован.

galanthus
()
Ответ на: комментарий от anonymous

https://godbolt.org/z/97jdvK4PW - вот наивный прогон

Инициализация матриц 4x4… cargo debug

— Старт бенчмарка —

Вариант 1 (Наивный, без аллокаций лейаута): 4.307524ms

==16685==

==16685== I refs: 17,455,474

==16685== I1 misses: 1,916

==16685== LLi misses: 1,872

==16685== I1 miss rate: 0.01%

==16685== LLi miss rate: 0.01%

==16685==

==16685== D refs: 11,369,666 (4,956,097 rd + 6,413,569 wr)

==16685== D1 misses: 2,964 ( 2,289 rd + 675 wr)

==16685== LLd misses: 2,351 ( 1,733 rd + 618 wr)

==16685== D1 miss rate: 0.0% ( 0.0% + 0.0% )

==16685== LLd miss rate: 0.0% ( 0.0% + 0.0% )

==16685==

==16685== LL refs: 4,880 ( 4,205 rd + 675 wr)

==16685== LL misses: 4,223 ( 3,605 rd + 618 wr)

==16685== LL miss rate: 0.0% ( 0.0% + 0.0% )

ниже cargo –release

[profile.release]

opt-level = 3

lto = true

codegen-units = 1

panic = «abort»

strip = true

Инициализация матриц 4x4…

— Старт бенчмарка —

Вариант 1 (Наивный, без аллокаций лейаута): 168.027µs

==17739==

==17739== I refs: 440,309

==17739== I1 misses: 1,753

==17739== LLi misses: 1,716

==17739== I1 miss rate: 0.40%

==17739== LLi miss rate: 0.39%

==17739==

==17739== D refs: 154,344 (105,080 rd + 49,264 wr)

==17739== D1 misses: 2,617 ( 2,044 rd + 573 wr)

==17739== LLd misses: 2,089 ( 1,557 rd + 532 wr)

==17739== D1 miss rate: 1.7% ( 1.9% + 1.2% )

==17739== LLd miss rate: 1.4% ( 1.5% + 1.1% )

==17739==

==17739== LL refs: 4,370 ( 3,797 rd + 573 wr)

==17739== LL misses: 3,805 ( 3,273 rd + 532 wr)

==17739== LL miss rate: 0.6% ( 0.6% + 1.1% )

anonymous
()
Ответ на: комментарий от yorshka

кароче я перепроверился, по другому тесту уже, почемуто включается общий перформанс и если написать лучше тех 2 тестов, там разница почему-то в наносекундах, типо как только на просто for врубаешь автовекторизацию на проект, типо всё, что можно драконически ускорится при выключенном флаге cpuid, ну оно и логично, потомучто вступает автовекторизация ) (в С интересно так же?) забавно, ну тогда не знаю, не знаю как валидно сравнивать в таком случае

anonymous
()
Ответ на: комментарий от BruteForce

Да я просто в порядке трэша и угара, атмосфера которых давно захватила этот тред. Ну и попиарить своё.

shdown ★★
()
Ответ на: комментарий от shdown

а что делает хэш для строки? зачем это нужно?

anonymous
()
Ответ на: комментарий от BruteForce

а в статье-обзоре нету сравнений с растом или с другой реализацией например map, по тому что я видел в валгринде по BVH почти одинаковые(это очевидно перенос структуры и логики почти 1 в 1), в примере выше просто я хотел доказать, что у программиста есть выбор, влепить ссылку или передать владение заморозив источник на момент функции например, к этому приходишь кстати пока разбираешься в целом с Раст, тоесть автоматизм есть, но не такой как в С++ с std::move, или в С с memcpy,memmove, где зивнул и всё…

anonymous
()
Ответ на: комментарий от BruteForce

Нет, конечно. Просто FNV-2 прям очень много где используется, и это демонстрация того, что оно сильно устарело (там множитель подбирался так, чтобы можно было сложениями-вычитаниями-сдвигами умножить, а не «дорогой» инструкцией умножения) и неоптимально (по одному байту обрабатываем T_T).

Я не мерял об xxHash, но оно проигрывает CityHash, где какая-то магия с «мы сделаем вот такое шаманство, чтобы на x86-64 оно вот так зашедулилось, а ещё сделаем rotate через два сдвига и or, компилятор распознает, а ещё наплодим огромное количество реализаций под разные размеры входных данных, а ещё вот эти все константы — мы не знаем, что это за константы, откуда они взялись, но вот этот чувак говорит, что они хорошие, а ещё…».

Ну, я, строго говоря, тоже не говорю, почему я выбрал вот эту константу (у меня она хотя бы одна), но я перебрал все простые < 2^32 и ещё очень много 64-битных.

shdown ★★
()
Последнее исправление: shdown (всего исправлений: 3)
Ответ на: комментарий от shdown

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

anonymous
()
Ответ на: комментарий от BruteForce

раз тут есть немного Раста, задам вопрос квинтессенцию, вот есть


//1
struct A{

}
//2
struct A{

}
//что-то .... какойто код о нем вопрос

fn main(){
  let A = A::new();
}

в чем суть? есть 2 одинаковых определения, но реализации чуть чуть разные, по типо simd/!simd как интересно это решается в Расте? понятно что можно назвать по разному/раскидать в разные mod.rs/lib.rs, а как это сделать так сказать красиво, типо удалить во время компиляции по проверке и воспользоваться 1 из 2 одинаковых, или я ошибаюсь и для самого создателя такой библиотеки это не возможно?

anonymous
()
Ответ на: комментарий от anonymous

в чем прикол? пока на С++ мы сравниваем автовекторизацию дефолтового кода, мы на 1 march, такой код на другой march может дать сбой, там может не быть -mavx2 -msse4.2, получается надо компилировать в векторизацию только расчет/функцию/вызов функции, чтобы бинарник был на младшую версию march и текущую, это как с флагом march=native в gentoo, и перекомпиляции ради native всего приходящего, таким образом лучше компилироваться сразу в таргет платформы по generic с включением выбора если есть версии ускорение/!ускорение.

anonymous
()
Ответ на: комментарий от shdown

чтобы пофиксить скорость, вам надо сделать симд хотябы для себя напишите враппер из интрисинков, откройте файл xmmintrin и внимательно его посмотрите, и подумайте как это укомплектовать в С++. потомучто руками писать инстринсики больно, а так врапер будет 1 типо, соотв 1 раз можно решить эти вопросы и посмотреть еффекты на регистрах симда типо.

anonymous
()
Ответ на: комментарий от anonymous

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

anonymous
()
Ответ на: комментарий от anonymous

я комментировать инстринсики не буду там в комментариях в файле по-сути всё написано.

anonymous
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.