Издательство Питер. Летняя распродажа

image

Привет, Хаброжители! На этой неделе у нас большие скидки. Подробности внутри.

image


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

Отдельные категории на сайте — Бестселлеры O’Reilly, Head First O’Reilly, Manning, No Starch Press, Packt Publishing, Классика Computer Science, программирование для детей, научно-популярная серия New Science.

Условия акции: 7—14 июля, скидка 40% на все бумажные книги по купону — Бумажная книга, скидка 50% на все электронные книги по купону — Электронная книга

ссылка на оригинал статьи https://habr.com/ru/company/piter/blog/509940/

Как я написал интро 4K на Rust — и оно победило

Недавно я написал своё первое интро 4K на Rust и представил его на Nova 2020, где оно заняло первое место в конкурсе New School Intro Competition. Написать интро 4K довольно сложно. Это требует знания многих различных областей. Здесь я сосредоточусь на методах, как максимально сократить код Rust.

Можете просмотреть демо-версию на Youtube, скачать исполняемый файл на Pouet или получить исходный код с Github.

Интро 4K — это демо, в которой вся программа (включая любые данные) занимает 4096 байта или меньше, поэтому важно, чтобы код был максимально эффективным. Rust имеет некоторую репутацию создания раздутых исполняемых файлов, поэтому я хотел выяснить, можно ли написать на нём эффективный и лаконичный код.

Конфигурация

Всё интро написано на комбинации Rust и glsl. Glsl используется для рендеринга, но Rust делает всё остальное: создание мира, управление камерой и объектами, создание инструментов, воспроизведение музыки и т. д.

В коде есть зависимости от некоторых функций, которые ещё не включены в стабильный Rust, поэтому я использую набор инструментов Nightly Rust. Чтобы установить и использовать этот набор по умолчанию, нужно запустить следующие команды rustup:

rustup toolchain install nightly rustup default nightly

Я использую crinkler для сжатия объектного файла, сгенерированного компилятором Rust.

Я также использовал shader minifier для препроцессинга шейдера glsl, чтобы сделать его меньше и удобнее для crinkler. Shader minifier не поддерживает вывод в .rs, так что я брал необработанную выдачу и вручную копировал её в свой файл shader.rs (задним умом ясно, что нужно было как-то автоматизировать этот этап. Или даже написать пул-реквест для shader minifier).

Отправной точкой послужила моё прошлое интро 4K на Rust, которое тогда мне казалось довольно лаконичным. В той статье также более подробная информация о настройке файла toml и о том, как использовать xargo для компиляции крошечного бинарника.

Оптимизация дизайна программы для уменьшения кода

Многие из наиболее эффективных оптимизаций размера никак не назовёшь умными хаками. Это результат переосмысления дизайна.

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

Анализ ассемблерного кода

В какой-то момент придётся посмотреть на скомпилированный ассемблер и разобраться, во что компилируется код и какие оптимизации размера стоят того. В компиляторе Rust есть очень полезная опция --emit=asm для вывода ассемблерного кода. Следующая команда создаёт файл ассемблера .s:

xargo rustc --release --target i686-pc-windows-msvc -- --emit=asm

Не обязательно быть экспертом в ассемблере, чтобы извлечь выгоду из изучения выходных данных ассемблера, но определённо лучше иметь базовое понимание синтаксиса. Опция opt-level = "z заставляет компилятор максимально оптимизировать код для наименьшего размера. После этого немного сложнее выяснить, какая часть кода ассемблера соответствует какой части кода Rust.

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

Дополнительные функции

Я работал с двумя версиями кода. Одна протоколирует процесс и позволяет зрителю манипулировать камерой для создания интересных траекторий. Rust позволяет определить функции для этих дополнительных действий. В файле toml есть раздел [features], который позволяет объявлять доступные функции и их зависимости. В toml соего интро 4K есть следующий раздел:

[features] logger = [] fullscreen = []

Ни одна из дополнительных функций не имеет зависимостей, поэтому они эффективно работают как флаги условной компиляции. Условным блокам кода предшествует оператор #[cfg(feature)]. Использование функций само по себе не делает код меньше, но сильно упрощает процесс разработки, когда вы легко переключаетесь между различными наборами функций.

        #[cfg(feature = "fullscreen")]         {             // Этот код компилируется только в том случае, если выбран полноэкранный режим         }          #[cfg(not(feature = "fullscreen"))]         {             // Этот код компилируется только в том случае, если полноэкранный режим не выбран         }

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

Одним из основных применений функций было включение лога и проверки ошибок для отладочной сборки. Загрузка кода и компиляция шейдера glsl часто завершались неудачно, и без полезных сообщений об ошибках было бы чрезвычайно трудно находить проблемы.

Использование get_unchecked

При размещении кода внутри блока unsafe{} я вроде как предполагал, что все проверки безопасности будут отключены, но это не так. Там по-прежнему выполняются все обычные проверки, и они дорого обходятся.

По умолчанию range проверяет все обращения к массиву. Возьмите следующий код Rust:

    delay_counter = sequence[ play_pos ];

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

Преобразуем код следующим образом:

    delay_counter = *sequence.get_unchecked( play_pos );

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

Более эффективные циклы

Изначально все мои циклы использовали выполнялись идиоматически как положено в Rust, используя синтаксис for x in 0..10. Я предполагал, что он будет скомпилирован в максимально плотный цикл. Удивительно, но это не так. Простейший случай:

for x in 0..10 {     // do code }

будет скомпилирован в ассемблерный код, который делает следующее:

    setup loop variable loop:     проверить условие цикла         если цикл закончен, перейти в end     // выполнить код внутри цикла     безусловно перейти в loop end:

тогда как следующий код

let x = 0; loop{     // do code     x += 1;     if i == 10 {         break;     } }

непосредственно компилируется в:

    setup loop variable loop:     // выполнить код внутри цикла     проверить условие цикла         если цикл не закончен, перейти в loop end:

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

Другая, гораздо более трудная для понимания проблема с идиоматическим циклом Rust заключается в том, что в некоторых случаях компилятор добавлял некоторый дополнительный код настройки итератора, который действительно раздувал код. Я так и не понял, что вызывает эту дополнительную настройку итератора, поскольку всегда было тривиально заменить конструкции for {} конструкцией loop{}.

Использование векторных инструкций

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

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

Чтобы использовать встроенные функции, я бы преобразовал следующий код

        global_spheres[ CAMERA_ROT_IDX ][ 0 ] += camera_rot_speed[ 0 ]*camera_speed;         global_spheres[ CAMERA_ROT_IDX ][ 1 ] += camera_rot_speed[ 1 ]*camera_speed;         global_spheres[ CAMERA_ROT_IDX ][ 2 ] += camera_rot_speed[ 2 ]*camera_speed;

в такое:

        let mut dst:x86::__m128 = core::arch::x86::_mm_load_ps(global_spheres[ CAMERA_ROT_IDX ].as_mut_ptr());         let mut src:x86::__m128 = core::arch::x86::_mm_load_ps(camera_rot_speed.as_mut_ptr());         dst = core::arch::x86::_mm_add_ps( dst, src);         core::arch::x86::_mm_store_ss( (&mut global_spheres[ CAMERA_ROT_IDX ]).as_mut_ptr(), dst );

что будет немного меньше по размеру (и гораздо менее читабельно). К сожалению, по какой-то причине это сломало отладочную сборку, хотя прекрасно работало в релизной. Ясно, что здесь проблема с моим знанием внутренних средств Rust, а не с самим языком. На это стоит потратить больше времени при подготовке следующего 4K-интро, поскольку сокращение объёма кода было значительным.

Использование OpenGL

Есть множество стандартных крейтов Rust для загрузки функций OpenGL, но по умолчанию все они загружают очень большой набор функций. Каждая загруженная функция занимает некоторое пространство, потому что загрузчик должен знать её имя. Crinkler очень хорошо сжимает такого рода код, но он не в состоянии полностью избавиться от оверхеда, поэтому пришлось создать свою собственную версию gl.rs, включающую только нужные функции OpenGL.

Заключение

Главная цель состояла в том, чтобы написать конкурентоспособное корректное интро 4K и доказать, что язык Rust пригоден для демосцены и для сценариев, где каждый байт имеет значение и вам действительно нужен низкоуровневый контроль. Как правило, в этой области рассматривали только ассемблер и C. Дополнительная цель состояла в максимальном использовании идиоматического Rust.

Мне кажется, что я довольно успешно справился с первой задачей. Ни разу не возникало ощущения, что Rust каким-то образом сдерживает меня или что я жертвую производительностью или функциями, потому что использую Rust, а не C.

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

ссылка на оригинал статьи https://habr.com/ru/post/509942/

Чеклист для проекта по машинному обучению

image

В этом посте я собрал чеклист, на который я постоянно ссылаюсь, работая над комплексным проектом по машинному обучению.

Зачем мне вообще нужен чеклист?

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

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

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

Как говорит Атул Гаванде в своей книге ”The Checklist Manifesto”,

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

Чеклист проектов по машинному обучению


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

1. Определите проблему с точки зрения высокого уровня

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

  • характер проблемы (контролируемая/неконтролируемая, классификационная/регрессионная),
  • тип решений, которые вы можете разработать
  • какие показатели вы должны использовать для измерения производительности?
  • является ли машинное обучение правильным подходом к решению этой проблемы?
  • ручной подход к решению проблемы.
  • неотъемлемые предпосылки проблемы

2. Определите источники данных и получите данные

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

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

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

3. Первоначальная разведка данных

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

Шаги:

  • используйте Notebook Jupyter, поскольку он обеспечивает простой и интуитивно понятный интерфейс для изучения данных.
  • определите целевую переменную
  • определите типы особенностей (категориальные, числовые, текстовые и т. д.)
  • проанализируйте соотношение между особенностями.
  • добавьте несколько визуализаций данных для легкой интерпретации влияния каждой функции на целевую переменную.
  • документируйте свои результаты исследований.

4. Исследовательский анализ данных для подготовки данных

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

  • Написание функций для преобразования данных и автоматизации процесса для предстоящих пакетов данных.
  • Напишите функции для очистки данных (вменяя пропущенные значения и обрабатывая резко отличающиеся значения)
  • Напишите функции для выбора и проектирования особенностей — удалите избыточные особенности, отформатируйте преобразование объектов, и другие математические преобразования.
  • Масштабирование особенностей (features) — стандартизация особенностей (features) .

5. Разработайте базовую модель, а затем изучите другие модели, чтобы отобрать лучшие

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

  • Обучите несколько часто используемых моделей, таких как модель наивного байеса, модель линейной регрессии, SVM и т. д., используя параметры по умолчанию.
  • Измерьте и сравните производительность каждой модели с базовой и со всеми остальными.
  • Используйте N-кратную перекрестную проверку для каждой модели и вычислите среднее и стандартное отклонение показателей эффективности по N-кратным показателям.
  • Изучите особенности, которые оказывают наибольшее влияние на цель.
  • Проанализируйте типы ошибок, которые допускают модели при прогнозировании.
  • Проектируйте функции по-разному.
  • Повторите вышеупомянутые шаги несколько раз (методом проб и ошибок), чтобы убедиться, что мы использовали правильные функции в правильном формате.
  • Составьте шорт-лист лучших моделей на основе их показателей эффективности.

6. Точно настройте свои модели из шорт-листа и проверьте наличие методов ансамбля

Это должен быть одним из решающих шагов, когда вы приближаетесь к своему окончательному решению. Основные пункты должны включать:

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

7. Документируйте код и сообщайте свое решение

Процесс коммуникации многообразен. Вы должны иметь в виду все существующие и потенциальные заинтересованные стороны. Поэтому основные пункты включают в себя:

  • Документируйте код, а также ваш подход ко всему проекту.
  • Создайте информационную панель, например, voila, или проницательную презентацию с визуализацией, которая не требует пояснений.
  • Напишите блог/отчет о том, как вы анализировали особенности, тестировали различные преобразования и т. д. Опишите свое обучение (неудачи и методы, которые сработали)
  • Закончите с основным результатом и будущим объемом (если таковые имеются)

8. Разверните свою модель в продакшен, мониторинг

Если ваш проект требует тестирования развертывания на реальных данных, вы должны создать веб-приложение или REST API для использования на всех платформах (web, Android, iOS). Основные пункты (будут варьироваться в зависимости от проекта) включают в себя:

  • Сохраните вашу окончательную обученную модель в файл h5 или pickle.
  • Обслуживайте свою модель с помощью веб-сервисов, Вы можете использовать Flask для разработки этих веб-сервисов.
  • Подключите источники входных данных и настройте конвейеры ETL.
  • Управляйте зависимостями с помощью pipenv, docker/Kubernetes (на основе требований масштабирования)
  • Вы можете использовать AWS, Azure или Google Cloud Platform для развертывания своего сервиса.
  • Делайте мониторинг производительности на реальных данных или просто для людей, чтобы они могли использовать вашу модель со своими данными.

Примечание. Чеклист может быть адаптирован в зависимости от сложности вашего проекта.

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:


Читать еще

ссылка на оригинал статьи https://habr.com/ru/company/skillfactory/blog/509946/

Зависимость от новостей: как слезть с крючка отслеживания событий. Личный опыт специалиста по цифровой психологии

image

Ежечасный беспорядочный скроллинг ленты в соцсетях, беглые взгляды на ТОП-5 новостей и последующее неизбежное залипание на них, а также бесчисленные переходы по подпискам с горячими новостями – все это часть опасной повседневности миллионов людей.

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

Автор этих строк также был заложником дофаминовой петли, созданной непрерывным потоком новостей и стремительными переходами от ссылки к ссылке. Все это происходило по десять-пятнадцать раз в сутки, нередко сопровождаясь пустыми дискуссиями в комментах. Как удалось преодолеть такую зависимость – в этой статье.

Новости в моей ладони

Если в эпоху аналоговых СМИ телевизионный зэппинг и его крайняя форма — грейзинг считались апофеозом медиа зависимости, то цифровой век, подаривший нам «весь мир в кармане», в корне поменял практики потребления новостей. Сегодня лишь немногие заглядывают в почтовый ящик в ожидании свежей хрустящей газеты, а тех, кто спешит к началу вечерних новостных выпусков, становится все меньше и меньше. Актуальный контент находится у нас прямо под пальцами. И при всех преимуществах мгновенного персонального доступа к информации и обилия точек входа, такая доступность скрывает неизбежный побочный эффект – нехимическая зависимость от постоянных новостных потоков.

image

Неполезный источник знаний

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

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

Опасность «горячих новостей»

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

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

Триггеры новостной аддикции

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

Данный эффект описан Ниром Эйялем в работе «Hooked. На крючке», где раскрывается цепочка формирования привычек постоянно обновлять почту, проверять новые сообщения в мессенджерах и соцсетях. В отношении новостного серфинга — все то же самое: ссылки на стартовых страницах поисковиков (Яндекс, Рамблер, Mail.ru) и мобильных браузеров (Opera, Chrome), а также Push-уведомления, всплывающие окна – все это «внедренные триггеры», заботливо презентуемые производителями софта и контента для усиления вовлеченности клиента (читай, усугубления зависимости).

image

Новостные ленты: зачем нам все это?

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

  1. Стремление переключиться с негативных мыслей о работе, проблем в личных отношениях и финансовых трудностей. Таким образом, мы даем краткосрочные передышки нервной системе от изнуряющих житейских рефлексий.
  2. Откладывание принятия сложного решения или начала работы. Залипание в соцсетях или новостном агрегаторе – популярное проявление эффекта прокрастинации. Благодаря иллюзии полезного времяпрепровождения (ведь новости – это важно!) мы стремимся обмануть самих себя, бесконечно оттягивая принятие решения или начала действия.
  3. Взращивание псевдокомпетентности. Благодаря нахождению в постоянном информационном потоке мы создаем ментальный конструкт эрудита – человека, который в курсе самых последних событий и трэндов, осведомленного собеседника. Подобное потребление новостей сопоставимо с неструктурированной навигацией по гиперссылкам при попытке изучить новое явление или понятие. Итогом такого познания становится поверхностное и фрагментарное представление о чем-либо, пустое и никчемное знание.

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

Как с этим бороться: личный опыт

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

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

  1. Осмыслить запрос. Каждый раз при включении смартфона и нажатии иконки браузера необходимо задавать себе вопрос «Зачем?». Ответ должен быть таким же четким – напр., посмотреть курс доллара, погоду на завтра, сделать конкретный запрос в поисковике. Питательная среда интернет-зависимости – работа на автомате, неосознаваемое действие по потреблению «того, что покажут», а самый эффективный антидот – осмысленность любого, даже самого небольшого действия.
  2. Только одна новость. Принципиальное следование правилу «один день – одна новость» ограничивает беспорядочный новостной серфинг. На практике это выглядит так: в конце дня я обращаюсь все к тому же списку событий дня, выбираю наиболее интересное и изучаю в первоисточнике. Общая продолжительность даже с учетом изучения комментариев – 10 -12 минут.
  3. Не комментировать. Каждый коммент, оставленный под публикацией, провоцирует последующий возврат к нему, чтобы посмотреть, поспорить, а где-то и потроллить. Осознав все это, я поставил запрет на любое текстовое выражение мнений под новостями.
  4. Цифровые детоксикации. Этот прием хорошо известен желающим сократить время, проводимое с цифровыми устройствами. В моем случае это сработало в полной мере. В период с 21.00 до 9.00 по будним – полный запрет на выход в интернет. То же самое, но на протяжении всего дня в воскресенье. Запрет распространяется на все, включая мессенджеры и почту. Только телефонные звонки. Лучше всего в этот период отключать передачу мобильных данных и Wi-fi.
  5. Отключение триггеров. Сразу после принятия решения я удалил приложения с новостями со смартфона, которые ранее регулярно присылали мне уведомления о важных и неважных событиях. В Telegram отписался от большинства каналов, а в оставшихся отключил уведомления. Также я стал использовать поисковики без информации на титульной странице (у Яндекса – ya.ru, у Google первая страница и так только с окошком ввода запроса). То же самое применил к мобильным браузерам, отключив ссылки на новости на стартовом экране.

Список литературы:

1. Olds J. “Self-stimulation of the brain; its use to study local effects of hunger, sex, and drugs". Science. 127 (3294): 315–24.
2. Травкина Н. «Дофаномика: как рынок обманывает наш мозг и как перестать проверять смартфон 80 раз в день».
3. Эйяль Н. «Hooked. На кючке. Как создавать продукты, формирующие привычку».

ссылка на оригинал статьи https://habr.com/ru/post/509948/

Сверхточный Raspberry PI Stratum 1 NTP сервер

В этой статье я расскажу, как собрать Stratum 1 NTP сервер на Raspberry PI для синхронизации времени за скромную сумму и навсегда забыть о проблемах, связанных с не совпадающим временем на всех ваших устройствах. А самое главное, он будет давать результат на два порядка точнее, чем обычный сервер.

В предыдущей статье, посвященной синхронизации времени по радио и СРНС (системы радионавигационной связи), я не успел рассказать про выбор приёмника GPS / ГЛОНАСС с выходом PPS. Между тем от этого зависит точность приёма сигнала, величина может составить от одной миллисекунды до нескольких микросекунд и зачастую это имеет решающее значение.

Для самого точного приема сигнала времени нужен приёмник GPS / ГЛОНАСС с выходом PPS. Дело однако в том, что на российском рынке не просто раздобыть устройство с такими характеристиками по доступной цене. Много таких моделей давно уже перестали выпускать, а в заброшенных интернет магазинах с версткой 1990-х остались лишь их описания с предложением подписаться на уведомление при поступлении товара.


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

  • Garmin GPS-18, не USB *** (приблизительная цена 10 тыс. р.)
  • GlobalSat MR-350P ****
  • Jackson Labs FireFly-II ***
  • Magellan Thales AC12 ***
  • Motorola Oncore GT+ ***
  • Navisys GR601-W ****
  • SkyTraq SKG16B ****
  • Trimble Lassen IQ ***
  • u-blox ANTARIS LEA-4T ***
  • u-blox EVK 6H ****
  • u-blox LEA SQ ****

4* Отличная производительность: gpsd распознает приёмник быстро и надежно, а отчеты сформировано полностью и правильно.

3* Хорошая производительность: gpsd с незначительными проблемами или задержкой распознаёт устройства, но отчеты сформировано полностью и правильно.

Если вас не пугает цена этих моделей, а также нет большого желания возиться с железками, можете не читать дальше. Приемник, подключенный к серверу по USB, или RS232 интерфейсу обеспечит гораздо большую точность определения времени, чем NTP сервер, работающий по tcp/ip. Но если путь самурая вам не чужд, тогда давайте собирать свой Raspberry PI NTP сервер с GPS синхронизацией времени.

Собираем Raspberry PI

Итак: берем следующие компоненты для нашего микро сервера.

  1. Плата Raspberry Pi 4 Model B, 4 GiB ОЗУ (6200 руб.);
  2. Корпус, например такой (890 руб.);
  3. Micro SD карта на 32 GiB, можно и 16 GiB; (540 руб.)
  4. GPS модуль на чипе u-blox NEO-M8 (1700 руб. с антенной);
  5. GPS антенна на 15 dB;
  6. Паяльник.

Вообще-то, u-blox NEO-M8 оснащен UART интерфейсом, но для PPS выхода необходимо припаять pin-3 на GPS модуле к соответствующему GPIO коннектору на плате Raspberri Pi. Модуль швейцарской компании завоевал популярность у специалистов и это не случайно, характеристики говорят сами за себя.

  • Поддерживаемые СРНС: BeiDou, Galileo, GNSS; GPS/QZSS, GLONASS;
  • Напряжение питания: 2.7…3.6 В;
  • Интерфейсы: UART, USB, SPI, DDC, I2C;
  • Поддерживаемые протоколы: NMEA 0.183 version 4.0, UBX (binary), RTCM 2.3;
  • Чувствительность при обнаружении: -167 дБм;
  • Чувствительность при слежении: -160 дБм;
  • Время холодного старта: 26 с;
  • Время горячего старта: 1.5 с;
  • Потребляемая мощность: 35 мВт;
  • Рабочая температура: -40…+85 °С;
  • Размеры: 16х12.2х2.4 мм

В такой конфигурации с новейшим оборудованием примерная общая цена Raspberry PI в собранном виде составит 9330 руб. Можно сэкономить, купив Raspberry PI 3, или четверку с 2 GiB ОЗУ. Можно еще сэкономить на GPS чипе, u-blox NEO-6M с антенной стоит около 650 руб. Тогда цена NTP сервера упадет до 5500 руб.

GPS/Глонасс модуль UBLOX NEO 8M

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

Источник сигнала времени Погрешность
GPS с атомными часами ±50 nSec
KPPS ±1 μSec
PPS ±5 μSec
Интерфейс USB 1.1 ±1 mSec
Интерфейс USB 2.0 ±100 μSec (100000 nSec)
NTP по сети ~±30 mSec

Kernel PPS (KPPS) отличается от PPS тем, что использует функцию ядра Linux / Unix для точной временной отметки изменения состояния в строке PPS. Обычный же PPS реализован в user-space. Если ядро Linux поддерживает KPPS через API RFC 2783, gpsd воспользуется им для увеличения точности.

Во многих дистрибутивах Linux имеется пакет pps-tools, который обеспечивает поддержку KPPS и устанавливает timepps.h заголовочный файл. Обязательно установите этот пакет.

(1:1146)$ sudo emerge -av pps-tools  Local copy of remote index is up-to-date and will be used. These are the packages that would be merged, in order:  Calculating dependencies... done! [binary   R    ] net-misc/pps-tools-0.0.20120407::gentoo  0 KiB  Total: 1 package (1 reinstall, 1 binary), Size of downloads: 0 KiB Would you like to merge these packages? [Yes/No]  

Таким образом, подключив GPS приёмник с PPS выходом по USB мы получаем 300-кратное повышение точности синхронизации времени. Чтение с чипа GPS на плате в режиме KPPS даёт прирост точности еще на два порядка.

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

Raspberry Pi GPS/RTC Expansion Board

Таких плат мало, и стоят они дорого. Разницу в цене вполне окупит приобретение паяльника и трудозатраты.

Установка ОС

Существует Raspberry PI OS, а. k. a. Raspbian, можно просто пойти по ссылке, скачать свежую версию и установить её. Многие так и делают, но давайте вспомним, что Raspberry PI 4 поддерживает 64-битную операционную систему, в то время как Raspberry PI OS пока имеет лишь 32-битные модификации Debian Linux для архитектуры Arm.

Существует такая точка зрения, что на 64-битная ОС неоправдана на Raspberry PI 4, так как нет возможности обеспечить прирост производительности из-за особенностей архитектуры и сборки. Мне эта точка зрения представляется сомнительной, об этом уже писали на Хабре — 64-битная ОС быстрее.

Существует порт Debian Linux для архитектуры arm64, однако дистрибутив Убунту для Raspberry PI имеет внятную страницу и инструкцию. На странице находим дополнительное подтверждение тому, что лучше выбрать 64-битную ОС.

Инвентарь для установки:

  • Raspberry Pi 4;
  • USB-C кабель питания для Pi 4;
  • Micro SD карта с установочным образом Убунту;
  • Монитор с выходом HDMI;
  • Кабель MicroHDMI;
  • USB клавиатура.

Следующий этап — запись установочного образа на Micro SD карту. Если у вас под рукой нет специализированной утилиты и программы под эти цели, в простейшем случае достаточно.

sudo dd if=/path/to/ubuntu-core-arm64.iso of=/dev/mmcblk0 status=progress

Точное название устройства видно в выводе dmesg при обнаружении нового устройства.

PM: Adding info for No Bus:179:0 device: 'mmcblk0': device_add PM: Adding info for No Bus:mmcblk0

Вставив Micro SD карту, подключив HDMI-монитор, USB-клавиатуру, и кабель питания загружаетесь в Ubuntu Server на Raspberry Pi. Имя пользователя и пароль по умолчанию ubuntu.

Настройка NTP сервера

  1. Если Raspberry PI включен в консольном режиме (headless), то для начала необходимо определить IP адрес устройства. С рабочей станции наберите следующую команду.
    (1:1151)$ arp -na | grep -i "dc:a6:32"

    Ели же Pi подключен к HDMI монитору и USB клавиатуре, пропустите шаги 1-2 и переходите сразу к установке пакетов.

  2. Подключитесь по ssh
    (1:1152)$ ssh ubuntu@<Raspberry Pi’s IP address>
  3. Установите необходимые пакеты.
    user@server ~$ sudo apt-get install aptitude user@server ~$ sudo aptitude install wpasupplicant gpsd chrony
  4. Настройте Wi-Fi соединение с помощью wpasupplicant.
  5. В Linux UART0 интерфейс Pi представлен файлом устройства /dev/ttyAMA0. Для того чтобы освободить UART0 интерфейс для GPS приёмника нужно поменять параметры загрузки ядра Linux. Необходимо отключить console=ttyAMA0,115200, заменив на console=tty1. Для этого в файле /etc/default/grub надо поменять GRUB_CMDLINE_LINUX_DEFAULT. Если существует файл, /boot/config.txt, в нем также можно задать те же опции.

    Raspberry Pi 4 имеет 6 UART-ов

    Название Тип Устройство Назначение
    UART0 PLO11 /dev/ttyAMA0 вторичный (Bluetooth)
    UART1 mini UART /dev/ttyS0 основной
    UART2 PLO11
    UART3 PLO11
    UART4 PLO11
    UART4 PLO11

    По умолчанию UART2-5 выключены.

    Как видно из названия, UART0 — полноценный серийный порт и он имеет более высокую производительность, чем обрезанный UART1, он же mini UART. Поэтому будет не лишним перевести Bluetooth на UART1 с тем, чтобы основной поток данных шел через UART0. Для этого в /etc/default/grub, или /boot/config.txt ставим enable_uart=1.

  6. В файле /etc/defaults/gpsd следует выставить.
    DEVICES="/dev/ttyAMA0 /dev/pps0" GPSD_OPTIONS="-n" USBAUTO="false"
  7. Запустите, или перезапустите gpsd.
    user@server ~$ sudo /etc/init.d/gpsd start user@server ~$ sudo /etc/init.d/gpsd restart
  8. Проверка работы модуля GPS.
    user@server ~$ cat /dev/ttyAMA0 user@server ~$ cgps -s user@server ~$ ppstest /dev/pps0
  9. Отредактируем файл /etc/ntp.conf.

    Все строки, содержащие сетевые публичные Stratum 1, 2 NTP сервера (такие, как pool [0-9].subdomain.pool.ntp.org) следует закомментировать, чтобы использовать лишь GPS/PPS источники данных.

    # GPS Serial data reference (NTP0) server 127.127.28.0 minpoll 4 fudge 127.127.28.0 flag1 1 time1 0.9999 refid GPS #flag1 - PPS on

    # GPS PPS reference (NTP1) server 127.127.22.0 minpoll 4 fudge 127.127.22.0 flag3 1 refid PPS #flag3 - enable KPPS API

    Верхняя запись NTP0 указывает на универсальный источник времени, доступный почти на всех устройствах GPS. Нижняя запись NTP1 определяет гораздо более точный PPS источник.

  10. Перезапустите ntpd
    user@server ~$ sudo /etc/init.d/ntpd restart

Использованные материалы

ссылка на оригинал статьи https://habr.com/ru/company/ruvds/blog/509890/