воскресенье, 21 июля 2024 г.

[life.audiophilia.diy] Итоговые впечатления от 15.4mm динамиков с литиево-магниевой диафрагмой

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

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

Как по мне, динамики дают "серединистый" звук, в котором НЧ и ВЧ заметно теряют громкость. Из-за чего у наушников получается непревзойденное трехмерность. По крайней мере в сравнении с тем, что есть у меня на руках.

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

Изначально в этих динамиках мне сильно не хватало веса на НЧ. Наушники были слишком "светлыми", хотелось большее баса.

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

В общем, с количеством НЧ смирился. А уж к качеству НЧ так вообще вопросов не было.

Засада же оказалась с ВЧ.

Литиево-магниевые динамики оказались просто недостаточно детальными на ВЧ, особенно в прямом сравнении с динамиками с LCP и DLC диафрагмами. Вот буквально, слушаешь литиево-магниевые, потом переключаешься на LCP и поражаешься насколько много в том же самом музыкальном материале всяких мелких отзвуков и призвуков на ВЧ. Как будто пробки из ушей достают.

Так что у литиево-магниевых динамиков все хорошо с тоналкой, просто шикарно с трехмерностью. К количеству НЧ, как оказалось, можно привыкнуть, а уж к проработке НЧ вопросов нет от слова совсем. Но с детализацией на ВЧ просто беда :(


Основными для меня в последние месяцы продолжают оставаться 15.4mm динамики с DLC и LCP диафрагмами. Причем, если раньше и DLC, и LCP мне казались недостаточно басовитыми, то сейчас LCP ощущаются просто как басхэдные со слишком большим количеством слегка "ватного" баса. DLC же, которые раньше ощущались, как "светлые" в сравнении с LCP, теперь кажутся практически тем, "что доктор прописал". Хотя по четкости и жесткости проработки НЧ, наверное, DLC уступают описанным выше литиево-магниевым динамикам, но компенсируют массой и громкостью НЧ.

Иногда слушаю и откровенно бюджетные 15.4mm динамики с композитной бериллиевой диафрагмой. Они хоть и бюджетные, с чрезмерной (для меня сейчас) массой НЧ, и "проваленной" серединкой, но зато с совершенно шикарными для своей цены ВЧ. Есть что-то в этих динамиках такое, что в первые два-три дня прослушивания невероятно очаровывает. Потом, правда, от количества НЧ устаешь и возвращаешься к DLC/LCP. Чтобы еще через месяц-два опять на пару дней вернутся к этому темному звуку с отличной детализацией на НЧ.

суббота, 20 июля 2024 г.

[life.business] Чего только в жизни не бывает...

Увидел некоторое время назад в ленте LinkedIn:

До сих пор пребываю в растерянности.

С одной стороны, очевидно, что 30 лет своей профессиональной деятельности занимался какой-то фигней. Мягко говоря.

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

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

понедельник, 1 июля 2024 г.

[life.cinema] Очередной кинообзор (2024/06)

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

Фильмы

Однажды в Ла-Рое (LaRoy, Texas, 2023). В принципе мне нравится такое. Но тут лично меня разочаровал финал. Даже не знаю почему, но вот разочаровал. Поэтому не получается оценить этот фильм высоко. Но на мой вкус вполне себе крепкий середнячок. Получше многих современных "фильмов".

Падение империи (Civil War, 2024). Кино довольно посредственное, а общее отношение к нему будет зависеть от ожиданий: если ждать, что это рассказ о гипотетической гражданской войне в США с пояснениями что из-за чего и как оно вообще, то фильм откровенно разочарует. Он не о том. А вот если рассматривать фильм как рассказ о том, как молодая девушка, жаждущая славы, превращается в матерого и циничного фронтового фотографа, вот тогда да, фильм оправдывает себя.

Границы безумия (Upon Entry, 2022). Во-первых, это никакой не триллер, это разговорная драма, в которой все держится на диалогах и, в принципе, неплохой игре актеров. Во-вторых, следить за происходящим было интересно, но вот финал разочаровал. Как по мне, не смогли авторы сделать настоящую кульминацию.

Побег из Могадишо (Mogadisyu, 2021). Нормально, вполне можно смотреть. Но это один из тех самых фильмов, где чувствуется разница между азиатским и европейским (или американским) кино. И вот эта самая "азиатчина" слишком уж бросается в глаза.

Сериалы

Шугар (Sugar, первый сезон, 2024). В принципе норм (хотя и здесь уместна обычная придирка к сериалам -- общий хронометраж можно было бы запросто уменьшить на одну-две серии). Но есть одно большое но: перед просмотром нельзя читать какие-либо описания или подробные отзывы на этот сериал. Иначе вы заранее узнаете один из ключевых твистов и это украдет у вас часть впечатлений.

Магазин для киллеров (Killeodeului syopingmol, первый сезон, 2024). Ну такое себе. Посмотреть можно. Но слишком уж много маразма и "роялей в кустах".

Не смог досмотреть

Я не киллер (Hit Man, 2023). Хватило терпеть дебилизм происходящего минут на 20, потом не выдержал. Ну или это кино на совсем уж подростковую аудиторию.

Онегин (2024). Не смог. Просто не смог осилить больше получаса, настолько сильно было желание обосрать происходящее в кадре.

Не для слабонервных (Trigger Warning, 2024). Редкая халтура. Мало того, что выстрелы из автоматов нарисованы на компьютере, так даже поленились нарисовать гильзы, которые при стрельбе из автомата должны были бы вылетать. Ну и окончательно добила "рукопашка" в исполнении Джессики Альбы.

Фильм вне категории

Фуриоса: Хроники Безумного Макса (Furiosa: A Mad Max Saga, 2024). Очень и очень двойственные чувства. С одной стороны, мне понравилась рассказанная история. Следить за происходящим было интересно. Да и претензий к актерской игре у меня нет. Так что как история из "вселенной Безумного Макса" очень даже OK. Но вот визуальная составляющая настолько халтурная на фоне "Дороги ярости", что просто караул. В общем, как по мне, в этом фильме был бы смысл только если бы по картинке он был бы такой же, как и "Дорога ярости". Однако, не получилось :(((

пятница, 28 июня 2024 г.

[prog.c++] Пример того, что могут творить оптимизирующие C++ компиляторы

В догонку к предыдущему посту про скорость самодельного UTF-8 валидатора. Захотелось добавить в это же сравнение и is_utf8 на базе SIMD.

Задействовать is_utf8 несложно, пишется очередная check_validity_with_*:

bool
check_validity_with_is_utf8_simd(std::string_view str)
{
   return is_utf8( str.data(), str.size() );
}

И все.

Но не совсем, т.к. эта новая check_validity только возвращает true/false, тогда как старые реализации еще и суммировали извлеченные code-point-ы:

bool
check_validity_with_restinio(std::string_view str, std::uint32_t & out)
{
   restinio::utils::utf8_checker_t checker;
   forconst auto ch : str )
   {
      if( checker.process_byte( ch ) )
      {
         if( checker.finalized() )
            out += checker.current_symbol();
      }
      else
         return false;
   }

   return true;
}

Т.е. делали лишнюю работу. А раз работа лишняя, то от нее хорошо было бы избавиться:

bool
check_validity_with_restinio(std::string_view str)
{
   restinio::utils::utf8_checker_t checker;
   forconst auto ch : str )
   {
      if( !checker.process_byte( static_cast<unsigned char>(ch) ) )
      {
         return false;
      }
   }

   return true;
}

OK, сделано. Можно запускать бенчмарк и...

И внезапно я вижу какие-то нереальные цифры:

***     restinio: 8us ***
***  decode_2009: 12us ***
***  decode_2010: 11us ***
*** simd_is_utf8: 49176us ***

Это GCC-13.2 под Windows на i7-8550u, ключи компиляции:

g++ -O2 -std=c++20 -o utf8_checker_speed-gcc13.exe *.cpp

В общем, явно что-то не то, ну не может работа выполняться за 8us там, где раньше было около секунды. Но что именно не то?

Оказалось, что компилятор GCC-13 настолько продвинут, что смог обнаружить отсутствие побочных эффектов в вызове обновленных версий check_validity_with_restinio, check_validity_with_decode_2009, check_validity_with_decode_2010. И ведь действительно, побочных эффектов там нет: на вход подаются одни и те же данные, на основе одних и тех же данных выполняются одни и те же вычисления. Соответственно, и результат вычислений всегда будет один и тот же.

Ну а раз результат всегда один и тот же, то нет смысла вызывать функции check_validity_with_restinio 100k раз, достаточно всего одного раза. Что GCC и сделал.

Отсюда и такие маленькие цифры -- это замер для всего одного вызова check_validity_with_*. А не для 100K вызовов, как задумывалось.

Тогда как в случае с is_utf8 компилятор не смог сделать выводов об отсутствии побочных эффектов (полагаю потому, что сама is_utf8 находилась в другой единице трансляции) и вызов check_validity_with_is_utf8_simd честно выполнялся 100K раз.

Чтобы понять что происходит пришлось заглянуть в ассемблерный выхлоп компилятора, чего я уже не делал лет сто, если не сто пятьдесят ;)

Еще прикольнее то, что GCC-11 не разобрался с отсутствием побочных эффектов у check_validity_with_restinio и честно вызывал ее 100k раз, тогда как вызовы check_validity_with_decode_2009 и check_validity_with_decode_2010 успешно "заоптимизировал". А вот GCC-13 смог справиться даже с utf8_checker_t из RESTinio. Что для меня выглядит ну совсем уже фантастикой.

Нужно сказать, что только GCC смог в такую крутую "оптимизацию". Ни с VC++, ни с clang ничего подобного не было.

PS. Если кому-то интересно, то вот результаты GCC-13.2 когда заставляешь его делать все 100k вызовов:

***     restinio: 535279us ***
***  decode_2009: 1197288us ***
***  decode_2010: 1137498us ***
*** simd_is_utf8: 53430us ***

вторник, 25 июня 2024 г.

[prog.c++] Любопытное на тему производительности самодельного проверяльщика UTF-8

Довелось недавно столкнуться с задачей проверки корректности UTF-8 представления. И в рамках этой задачи вышел вот на это замечательное описание с примерами двух реализаций: Flexible and Economical UTF-8 Decoder.

Очень мне понравились оба тамошних решения (для простоты буду называть их "решение от 2009-го" и "решение от 2010-го" годов, по датам в копирайтах). Просто и лаконично. Да еще и гибко, можно затачивать хоть под проверку, хоть про декодирование с восстановлением после ошибок.

Поскольку у нас в RESTinio есть что-то аналогичное, но гораздо более объемное по числу строк, то подумалось, что можно было бы заменить наш многострочный utf8_checker на более компактный.

Но прежде чем сделать это попробовал провести простейшие сравнения производительности. И вот тут-то меня ждал сюрприз...

На основном рабочем Windows-ноутбуке с i7-8550U и VisualStudio 2022 (17.10.3) примитивный бенчмарк показывает следующие результаты:

***    restinio: 1240136us ***
*** decode_2009: 1784796us ***
*** decode_2010: 1774765us ***

Компиляция выполнялась так: cl -EHsc -O2 -DNDEBUG -utf-8 -std:c++20

На этом же Windows-ноутбуке под GCC-13.2.0 (из MinGW-w64) получаются следующие числа:

***    restinio: 435519us ***
*** decode_2009: 977052us ***
*** decode_2010: 566962us ***

Компиляция выполнялась так: g++ -O2 -std=c++20

На резервном Linux-ноутбуке с i7-6600U и GCC-13.1 этот же бенчмарк дает следующие числа:

***    restinio: 915891us ***  
*** decode_2009: 873742us ***  
*** decode_2010: 809853us ***

Но еще интереснее оказывается с GCC-11 на том же Linux-ноутбуке:

***    restinio: 941621us ***  
*** decode_2009: 1857220us ***  
*** decode_2010: 2047872us ***

Т.е., похоже, в GCC-13 оптимизатор серьезно прокачали, отсюда и гораздо лучшие результаты для решений от 2009-го и 2010-го годов под GCC-13.

Но намного больше пищи для размышлений дал clang-18:

***    restinio: 2108439us ***  
*** decode_2009: 1775339us ***  
*** decode_2010: 2012727us ***

Т.е. оптимизатор в clang-е с решениями 2009-го и 2010-го годов справился на уровне GCC-11, но вот наш код из RESTinio он настолько же сильно, как GCC-13, оптимизировать не смог.

Ну и для полноты картины результаты clang-16 с того же Linux-ноутбука:

***    restinio: 2379565us ***  
*** decode_2009: 3222073us ***  
*** decode_2010: 1839321us ***

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

Меня удивило другое: насколько разные результаты можно получить на одной и той же платформе с разными версиями одного и того же компилятора (не говоря уже о разных компиляторах).

Если взять специфику наших открытых библиотек, которые распространяются в исходниках, а затем компилируются на неизвестно каких платформах неизвестно какими компиляторами, то насколько уместно заниматься низкоуровневыми оптимизациями? Типа отшлифуешь все до последней микросекунды на Windows с VC++, а на Linux-е и 11-ом GCC, напротив, получишь просадку производительности.

PS. Я понимаю, что это негодный бенчмарк. Всего один набор тестовых данных. Весь код в одном файле, что не есть хорошо, если разнести функции по разным .cpp-файлам результаты могут отличаться, например, когда каждая функция декодирования помещается в отдельный C++ файл, то результы с GCC-13 под Linux-ом на i7-6600U меняются в пользу реализации от RESTinio:

***      restinio: 612732us ***
***   decode_2010: 820765us ***  
***   decode_2009: 855889us ***  

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

вторник, 18 июня 2024 г.

[prog] Один из признаков того, что с вашим кодом не все в порядке

Очень простой маркер трансформации в говнокод: закомментированные куски без пояснения причин почему эти куски были закомментированы и до какого времени они должны в таком виде оставаться.

Т.е. если вы видите в кодовой базе что-то вроде:

data_manager::data_manager(
  data_set_id id,
  raw_data_storage_shptr raw_data_storage,
  access_manager_shptr access_manager,
  modification_mode mode,
  logger log)
  : base_type{ id,
      std::move(raw_data_storage),
//     std::move(access_manager)
//     mode
    }
{
//  _id = id;
//  _storage = std::move(raw_data_storage);
//  _access_manager = std::move(access_manager);
  setup_access_manager(std::move(access_manager));
  setup_mode(mode);
  setup_logger(std::move(log));
}

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

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

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

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

Например:

data_manager::data_manager(
  data_set_id id,
  raw_data_storage_shptr raw_data_storage,
  access_manager_shptr access_manager,
  modification_mode mode,
  logger log)
  : base_type{ id,
      std::move(raw_data_storage),
//FIXME(eao197): access_manager и mode должны были бы передаваться
//в base_type, но там временно пришлось убрать такой конструктор.
//Нужно вернуться к передаче access_manager и mode в конструктор
//базового класса после того, как base_type будет отрефакторен.
//     std::move(access_manager)
//     mode
    }
{
  //FIXME(eao197): установка access_manager и mode должна
  //быть со временем перенесена в конструктор base_type.
  setup_access_manager(std::move(access_manager));
  setup_mode(mode);

  setup_logger(std::move(log));
}

PS. Был в моей карьере один случай двухдневного сеанса отладки кода, который до сих пор вспоминается с содроганием. Выглядел этот код как откровенное Г и состоял на 50% вот таких вот закомментированных кусков без всяких пояснений. Причем ладно бы в начале файлов были раскомментированные, актуальные строки, а в конце -- закомментированные, уже не нужные. Так нет, все это было вперемешку. Бррр. Как вспомню, так вздрогну.

воскресенье, 16 июня 2024 г.

[prog.java] Листая старенький айпад или как же похорошела Java за последние 14 лет ;)

Довелось тут давеча вспомнить когда в последний раз программировал на Java. Почему-то думал, что было это в 2012-ом, а оказалось, что в 2010-ом. Интересно сейчас, спустя 14 лет, перечитывать собственные старые впечатления. Особенно вот эти соображения о том, чего лично мне тогда не хватало в Java. И тем забавнее обнаружить, что часть из описанного мной тогда, в современной Java уже есть: это и автоматический вывод типов переменных, и лямбда функции, и try-with-resources.

Как же похорошела Java за эти годы! ;)

Только вот желания программировать на Java как не было, так и нет :)))

PS. Да и с кроссплатформенностью у .NET и C# стало куда как лучше.