Pull to refresh
-8
0
Александр @iCpu

Бот

Send message

Это был актуальный комментарий, году эдак в 2008, когда на Хабрахабр политоту не пускали на пушечный выстрел. И даже в 2012 это было ещё более-менее актуально.

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

А потом хабр сам в себя всосал околоИТ и "актуальные жаренные" новости. И всё заверте...

Я получил -10 за свою единственную статью (у которой ни единого минуса в оценках). И ещё -5 за слова

Аккуратнее с мнениями хабровчан. Далеко не все они - граждане РФ. И далеко не все из них пишут с территории РФ. Но мнение, как и пупок, из них имеет почти каждый первый.

в ответ на конкретный вопрос про конкретную ситуацию в конкретном месте.

Хабр уже лет 8 как укатился в какое-то рукопожатное говно, если не больше.

Вы прочитали миниатюру "Пропаганда вражеской стороны".

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

Всё так.

Ты не мог не оформлять военный билет, за ним всех пацанов из школы в 16 лет отправляют. Все получают карту военного учёта. А потом в 18 лет повторно отправляют всем классом\колледжем - и все получают военные билеты. Кто после службы, а кто сразу по отсрочке. Если ты его не оформлял ни тогда, ни тогда, что ж... Не хорошо.

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

А вот риск получить штраф у тебя не маленький. Не 100%, но и не 0.01%.

1) В военкомат приходишь по месту регистрации. Если зарегистрирован в Твери - за военником надо ехать в Тверь. И там сообщить, что ты в Москве окучиваешься.
2) Военный призыв до 30 лет.
3) Мобилизовать тебя просто так не будут: в мобики даже на момент активной фазы брали не всех.
4) За нарушение сроков подачи документов (у нас в законах написано, через сколько нужно на учёт вставать при совершеннолетии\получении гражданства\смене ПМЖ) может прилететь штраф 5к. Прилетает далеко не всем, но психологически нужно быть готовым.
5) Аккуратнее с мнениями хабровчан. Далеко не все они - граждане РФ. И далеко не все из них пишут с территории РФ. Но мнение, как и пупок, из них имеет почти каждый первый.

И третье, это прекрасные камеры, хорошая оптика и большая матрица. Сравните характеристики КАМ-О с Mastcam-Z. Внезапно, КАМ-О и КАМ-С по многим параметрам вполне на уровне: в чём-то уступают, в чём-то лучше.

А вот это вот "У меня на хуавее снимки красивее" даже не начинайте. Ваш "хуавей" сейчас не в космосе летит, одним боком нагреваясь до 120 градусов, а другим охлаждаясь до -180 градусов. Ваш "хуавей" не в вакууме сейчас, пережив перед этим ни капельки не комфортный запуск в космос. На ваш "хуавей" сейчас не светит солнечные 0,5 миллигрей в сутки. У вашего "хуавея" нет ограничений ни по энергопотреблению, ни по каналу связи, ни по тепловыведению. И даже так, ваш "хуавей" полагается на кучу алгоритмов улучшения картинки, без которых лишние мегапиксели лишь преумножают боль.

Можно, декомпозиция (хоть ФПшная, хоть ООПшная) именно про это. Сложные задачи сложны именно потому, что найти такое представление, ну, сложно.

"в виде совокупности малого числа простых задач" - в общем случае, нельзя. Можно "в виде совокупности некоторого числа более простых задач". Вроде нюансы и софистика, но если сам математический алгоритм на 10 000 различных операций, ты как их не переписывай, меньше 10 000 операций не получится. И как их не записывай, особо понятнее они не станут.

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

Unity Game Engine? Как бы самый первый пример, который приходит в голову. Можно сколько угодно сейчас попу рвать, "а ты вообще его видел", "а ты попробуй туда запихни сложный функционал", но на нём выходят тысячи игр самой разной сложности игровых механик. И выпускают их даже люди со знаниями уровня "Heoll Wolrd!". Значит, их ООП подходы работают.

С другой стороны, я не встречал на профильных площадках ни одного упоминания игрового движка на Haskell, например. Да и на других чисто функциональных языках. Я не говорю, что их нет, или что функциональный подход плох. Но вот как есть.

Что за правила вызова тут подразумеваются?

Зависит от языка и среды. Я не настолько глуп, чтобы под одну гребёнку грести плюсы, жабу и жабоскрипт (которые все трое ООП).

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

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

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

А компилятор должен это делать? В какой из букв ООП это сказано? А если он гарантировал, а мне нужно эту гарантию нарушить из-за изменившихся условий, то что? Кто первый пойдёт в пешее эротическое?

Как бы, гарантии должен давать не компилятор, а создатель кода для класса. Его задача - дать удобный предсказуемый функционал. И если для этого нужно иметь скрытые состояния и неявные вызовы (а ты попробуй окошки одинаковыми на winapi и на x11 нарисуй без говнокода под капотом и кучи скрытых состояний), значит, они будут лежать скрытыми под капотом. И будьте уверены, в Хаскеле будет тот же самый говнокод скрыт под примерно такими же вызовами, с поправкой на язык.

И не надо закатывать глазки и устало вздыхать. Вот человек поделился своей историей https://habr.com/ru/companies/sportmaster_lab/articles/728880/comments/#comment_25471164. Вполне реальная, у меня так же бомбануло, когда сервак с другой стороны перестал отдавать нормальные данные с первой попытки, а стал спамить ошибками и невалидными ответами с 200-м кодом. И мне пришлось переписывать класс загрузчика несколько раз, добавляя всё больше скрытых состояний, "дазаткнизьмов" и валидаторов. Но клиентский код почти не изменился (кроме возможности передать собственный валидатор). Публичный интерфейс не поменялся. Класс, как чёрная коробка, остался бинарно совместим со своей предыдущей версией. Значит, свою задачу ООП выполнило. Не нравится? Да вообще всё равно.

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

Но как пример перехода большой задачи в сложную - вполне себе хороший. И на ООП скрыть всякие досылки, keep-alive и прочие пулы, - куда проще, чем на вот такой уже выоптимизированной до свищей и табличных обработок кодовой базе.

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

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

Нельзя представить сложную задачу в виде совокупности малого числа простых задач. Она на то и сложная, чтобы быть месивом ещё на этапе формулировки. А у нас всё чётко: garbage in - garbage out. Если формулировка месиво, то и реализация соответствует. Через какие решения её не реализуй.

Но, позвольте, разве ООП не решает свою задачу? Разве наследование публичного интерфейса со всеми обязательствами на уровне языка не решает проблему соответствия правил вызова между разными объектными файлами? Разве структурирование в классы и объекты не повышает предсказуемость поведения кода? Всё они успешно делают, и достаточно оптимально.

Если не решают, значит, вы их неправильно готовите.

Вот, кстати, да. Очень важный момент: оптимизировать надо только то, что не оптимально, и только так, чтобы повышалась эффективность в контексте данной задачи.

В контексте конкретно поставленной задачи площадной числодробилки, "чистый код" с виртуальными вызовами (которые почему-то не были выоптимизированы, видимо не хватило флагов компилятора) будет хуже "грязного". Вот только после перехода от switch к таблице констант читаемость кода понизилась значительно.

Но "числодробилка" - не всегда основная или даже значимая задача. Есть например задача "рисовать форточки". И я получал награду "лучший порноактёр года" все эти форточки реализовывать через свичи и юнионы. Хватит! Навинапишился я с этими хвиндами! Вот конкретно тут мне куда проще и понятнее построить пару лишних фабрик, и рядом табачную мануфактуру "Manual" задокгенить, чтобы было чего потом покурить.

Кроме того, товарищ @JustJeremy нам немного насвистел в уши. Фигуры в реальном коде определяют через координаты и иные параметры. Я ещё ни разу не встречал реального кода, где треугольник бы определяли через основание и высоту (хотя для ряда задач, согласен, это возможно). То есть для обоснования своей спорной точки зрения "Ой, смотрите, как красиво код получается табличкой!" нам подсунули изначально туфту - и из неё делают какие-то далеко идущие выводы.

А давайте, товарищ@JustJeremy, немного повысим ставки. А давайте у нас там будет не вычисление площади для искусственно подобных фигур, а, например, различные алгоритмы хеширования? И не просто sha1 и md5, а ещё и ГОСТовые возьмём! А для оправдания виртуализации, пусть у нас будут различные таблицы инициализации, не только стандартные, но и определённые пользователем. И соль! Покажите, как у вас красиво все структуры поместятся в union, как красиво табличкой сложатся функции, и как потрясающе на порядки вырастет производительность из-за замены виртуальных методов на свищи!

И не надо свистеть, что "Это другое". Это - то самое.

UPD: Оп! Не сразу заметил, что это перевод. Ну, что же. Перевели? Значит, подумали, что статья хорошая. Ну вот и отдувайтесь за автора.

Ладно, согласен, неправильно выразился. llvm использует код для сишного restrict при оптимизации использования ссылок. Из-за этого в определённый момент такая оптимизация не работала.

Ну, то есть, спора по поводу явной большей семантической корректности Сишного и Плюсового кода нет? Ок.

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

Потому что & и &mut на расте - это прямое переиспользование сишного restrict. И способы обхода этого ключевого слова на Си известны.

Вы указали на безошибочный код с лишним копированием и сказали: "А на Rust мне язык не даёт так сделать."
Я показал корректный код, в котором лишнее копирование никогда не происходит. При этом, то же самое можно сделать через простую переменную и копирование, просто тогда всегда будет оверхед по памяти.
Но вы не довольны. Хотя код на расте явно дырявый: компилятор не может бесконечно глубоко в дерево уходить, на каком-нибудь пуле объектов всё закончится. И даже если у вас попытку перезаписи поймает менеджер памяти, где он это сделает и куда вывалится? У вас есть там нужная обработка? Нет? Ой-ой-ой...

Но если хотите, почему нет? Проведите тесты производительности в оптимистичном (частота помещения в себя 0%), обычном (5%), пессимистичном (30%) и терминальном (100%). В один и несколько потоков. Запишите график использования и фрагментации. Потом повторите, запихнув между умножениями другие операции. Не забываем проверять с разными ключами компилятора: не только с -O, но и c SSE\AVX, с необычными оптимизациями разных компиляторов. Мы же взрослые дяди? Можно ещё и необычные std подключать, реализация от микрософта или gcc далеко не всегда и не во всём топчик. И тестить на всех системах, от древних Windows до новых Android, промежая сборками под микроконтроллеры и одноплатники.

Посмотрим на фрагментацию памяти во всех режимах!

Это же вы хотите всё делать как в продакшене? Прошу! Доказывайте, как серьёзный дядя, что такая реализация хуже, по сути, никакой в Расте.

А давайте ещё представим что у нас многопоток? И не простой, а помесь OpenMP и MPI. Не будем расслабляться!
А потом давайте представим, что у нас могут быть MatrixView с частично пересекающимися областями, и что сравнения указателей не хватит. А чо нет-то?
Что ещё бы представить? Можно ещё разряженные матрицы. Или потоки матричных преобразований с оптимизатором. Или что-нибудь ещё в этом духе. Красиво жить не запретишь!

А, может, не будем представлять? Это такая редкая операция, что вы на неё положили болт 50ой резьбы. Вы её просто отбросили как невозможную в расте. Хотя, на деле, ничего невозможного в ней нет: прилетит ссылка через четвёртые руки - и всё равно заломает программу, так или иначе.

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

Ну вот, добавили овердофига бойлерплейта, а сам метод, к которому предъявлялись претензии, так и не реализовали, ну как же так xD

Месье любит несвежие портянки?

Кстати, как вы думаете, move конструктор будет как-то осмысленно отличаться от копирования в данном случае?

Хм... А вот сейчас я задумался. У std::array вообще есть конструктор перемещения? Вроде, нет. Ладно, уел)) А std::vector точно просто обменивает указатели при перемещении.

В общем, как же должен выглядеть "правильный идиоматичный код на С++", который бы не имел тех же проблем (из описанных в посте), что и текущий пример, так и осталось неясным.

Конкретный пример некорректен. Почему нельзя матрицу умножать на себя и поместить результат в себя же? Потому что какой-то DancingOnWater решил, что конкретно этот случай он не будет реализовывать? Тогда обложись assert'ами или поменяй интерфейс функции.
Но если ты хочешь при этом интерфейсе работоспособность оставить, тогда, конечно, нужна обвязка вроде такой.

Претензию к тому, что язык допускает передачу одной и той же переменной и как константную ссылку, и как не константную, и что разработчик 99% продолбится в глаза мимо этого случая, принимаю.

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

Можно промахнуться даже мимо кнопки "сделать хорошо". Ошибиться можно и в Rust'е, там тоже полно подводных камней и неявных правил. Вам уже сверху накидали примеров. Константность по умолчанию важна только если ты впервые язык видишь и вообще ничего не читал. У меня сейчас на автомате const& пишется везде, а потом думается в другую сторону.

М-да, даешь пример, чтобы подсветить идею, а тут начинается...

Пардонте, нужно было пример лучше выбирать. На каком-нибудь 03 или 07 стандарте я бы согласился, что у плюсов всё очень не просто с выразительностью или с безопасностью. В 20+ к таким мелочам докапываться - это просто оскорбительно.

1
23 ...

Information

Rating
Does not participate
Location
Новосибирск, Новосибирская обл., Россия
Date of birth
Registered
Activity