Pull to refresh

Мозг и системы машинного обучения: сравнение масштабов

Reading time18 min
Views8.6K

Эпистемологический статус: весьма неопределённый. В литературе приводятся обширные, но ненадёжные данные, и в этой статье я делаю некоторые весьма грубые допущения. Тем не менее, я удивлюсь, если мои заключения отличаются от истины более чем на 1-2 порядка.

В настоящее время мозг — это единственный известный пример AGI (сильного искусственного интеллекта). Даже мелкие животные с крошечными мозгами демонстрируют впечатляющую степень владения сильным искусственным интеллектом, в том числе, гибкость и агентное поведение в сложном мире, характеризующемся высокой неопределённостью. Если мы хотим понять, в какой степени современное машинное обучение приблизило нас к AGI, то стоит попробовать количественно оценить мощность мозга. Хотя уже проделано много отличной работы, дающей представление о возможностях мозга и о том, как эти данные экстраполируются на хронологию развития ИИ, мне никогда не удавалось по-настоящему разобраться в вопросе кроме как на практике. Так что ниже я решил проанализировать мозг в терминах современного машинного обучения и попытаюсь на основе этого анализа предположить, на что можно рассчитывать на текущем этапе разработки AGI.

Читать далее
Total votes 41: ↑36 and ↓5+31
Comments26

Барьеры памяти и неблокирующая синхронизация в .NET

Reading time7 min
Views57K

Введение


В этой статье я хочу рассказать об использовании некоторых конструкций, применяющихся для осуществления неблокирующей синхронизации. Речь пойдёт о ключевом слове volatile, функциях VolatileRead, VolatileWrite и MemoryBarrier. Мы рассмотрим, какие проблемы вынуждают нас воспользоваться этими языковыми конструкциями и варианты их решения. При обсуждении барьеров памяти вкратце рассмотрим модель памяти .NET.
Читать дальше →
Total votes 63: ↑62 and ↓1+61
Comments18

Эффективное и комплексное устранение утечек памяти в Android

Level of difficultyMedium
Reading time7 min
Views5.6K

Цель этой статьи — изучить эффективные и комплексные решения по нахождению и устранению утечек памяти в контексте Android-разработки. Стоит понимать, что утечка памяти чаще всего возникает из-за незнания технологии или собственного кода на подкапотном уровне, поэтому основной целью является научиться правильно писать код, учитывая специфику работы Java Memory Model, Garbage Collector и File descriptor.

Читать дальше
Total votes 7: ↑5 and ↓2+3
Comments5

1000-мерный куб: можно ли сегодня создать вычислительную модель человеческой памяти?

Reading time36 min
Views26K
image

Сегодня утром на пути к кампусу Беркли я провёл пальцами по листьям ароматного куста, а затем вдохнул знакомый запах. Я делаю так каждый день, и каждый день первое слово, которое всплывает в голове и приветственно машет рукой — это шалфей (sage). Но я знаю, что это растение — не шалфей, а розмарин, поэтому я приказываю шалфею успокоиться. Но слишком поздно. После rosemary и sage я не могу помешать появлению на сцене петрушки (parsley) и чабреца (thyme), после чего в голове возникают первые ноты мелодии и лица на обложке альбома, и вот я уже снова оказался в середине 1960-х, одетый в рубашку с огурцами. Тем временем розмарин (rosemary) вызывает в памяти Роуз Мэри Вудс (Rosemary Woods) и 13-минутный пробел (хотя теперь, проконсультировавшись с коллективной памятью, я знаю, что это должны быть Роуз Мэри Вудс и пробел в 18 с половиной минут). От Уотергейта я перепрыгиваю к историям на главной странице. Потом я замечаю в ухоженном саду ещё одно растение с пушистыми серо-зелёными листями. Это тоже не шалфей, а чистец (lamb’s ear). Тем не менее, sage наконец получает свою минуту славы. От трав я переношусь к математическому ПО Sage, а потом к системе противовоздушной обороны 1950-х под названием SAGE, Semi-Automatic Ground Environment, которой управлял самый крупный из когда-либо построенных компьютеров.

В психологии и литературе подобные мыслительные блуждания называются потоком сознания (автор этой метафоры — Уильям Джеймс). Но я бы выбрал другую метафору. Моё сознание, насколько я ощущаю, не течёт плавно от одной темы к другой, а скорее порхает по ландшафту мыслей, больше похожее на бабочку, чем на реку, иногда прибиваясь к одному цветку, а затем к другому, иногда уносимая порывами ветка, иногда посещающая одно и то же место снова и снова.
Читать дальше →
Total votes 38: ↑35 and ↓3+32
Comments10

Введение в неблокирующие алгоритмы

Reading time8 min
Views23K

Неблокирующие алгоритмы широко применяются в ядре Linux когда традиционные примитивы блокировки либо не могут быть использованы, либо недостаточно быстры. Эта тема многим интересна и время от времени всплывает на LWN. Из недавнего — вот эта июльская статья, которая собственно и сподвигла меня написать свою серию. Ещё чаще разговор заходит про механизм read-copy-update (RCU — руководство 2007 года всё ещё актуально), подсчёт ссылок, и способы сделать более понятные, высокоуровные API ко всему этому разнообразию. Ну а сейчас вас ждёт погружение в идеи, стоящие за неблокирующими алгоритмами, а также их использованием в ядре.


Знание низкоуровневой модели памяти в целом считается продвинутым уровнем понимания, которого страшатся даже опытные программисты-ядерщики. Словами нашего редактора (из его июльской статьи): «Понять модель памяти можно лишь правильно повёрнутым мозгом». Говорят, что моделью памяти Linux (и файлом memory-barriers.txt в частности) можно пугать детей. Порой для достижения эффекта достаточно всего лишь рявкнуть “acquire” или “release”.


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

Читать дальше →
Total votes 39: ↑36 and ↓3+33
Comments60

Приёмы неблокирующего программирования: атомарные операции и частичные барьеры памяти

Reading time8 min
Views11K

В первой статье цикла мы познакомились с простыми неблокирующими алгоритмами, а также рассмотрели отношение “happens before”, позволяющее их формализовать. Следующим шагом мы рассмотрим понятие «гонки данных» (data race), а также примитивы, которые позволяют избежать гонок данных. После этого познакомимся с атомарными примитивами, барьерами памяти, а также их использованием в механизме “seqcount”.


С барьерами памяти некоторые разработчики ядра Linux уже давно знакомы. Первый документ, содержащий что-то похожее на спецификацию гарантий, предоставляемых ядром при одновременном доступе к памяти — он так и называется: memory-barriers.txt. В этом файле описывается целый зоопарк барьеров вместе с ожидаемым поведением многопоточного кода в ядре. Также там описывается понятие «парных барьеров» (barrier pairing), что похоже на пары release-acquire операций и тоже помогает упорядочивать работу потоков.


В этой статье мы не будем закапываться так же глубоко, как memory-barriers.txt. Вместо этого мы сравним барьеры с моделью acquire и release-операций и рассмотрим, как они упрощают (или, можно сказать, делают возможной) реализацию примитива “seqcount”. К сожалению, даже если ограничиться лишь наиболее популярными применениями барьеров — это слишком обширная тема, поэтому о полных барьерах памяти мы поговорим в следующий раз.

Читать дальше →
Total votes 11: ↑11 and ↓0+11
Comments3

Приёмы неблокирующего программирования: полные барьеры памяти

Reading time9 min
Views8.6K

В первых двух статьях цикла мы рассмотрели четыре способа упорядочить доступ к памяти: load-acquire и store-release операции в первой части, барьеры чтения и записи в память — во второй. Теперь пришла очередь познакомиться с полными барьерами памяти, их влиянием на производительность, и примерами использования полных барьеров в ядре Linux.


Рассмотренные ранее примитивы ограничивают возможный порядок исполнения операций с памятью четырьмя различными способами:


  • Load-acquire операции выполняются перед последующими чтениями и записями.
  • Store-release операции выполняются после предыдущих чтений и записей.
  • Барьеры чтения разделяют предыдущие и последующие чтения из памяти.
  • Барьеры записи разделяют предыдущие и последующие записи в память.

Внимательный читатель заметил, что одна из возможных комбинаций в этом списке отсутствует:

Чтение выполняется... Запись выполняется...
… после чтения smp_load_acquire(), smp_rmb() smp_load_acquire(), smp_store_release()
… после записи ??? smp_store_release(), smp_wmb()
Оказывается, обеспечить глобальный порядок записей и последующих чтений из памяти гораздо сложнее. Процессоры вынуждены прилагать отдельные усилия для этого. Сохранение такого порядка стоит недёшево и требует явных инструкций. Чтобы понять причину этих особенностей, нам придётся спуститься на уровнь ниже и присмотреться к тому, как процессоры работают с памятью.
Читать дальше →
Total votes 10: ↑10 and ↓0+10
Comments4

В чём опасность слабой модели памяти ARM на примере конкретного эксплоита

Reading time9 min
Views9.8K


Процессоры ARM приходят к нам всерьёз и надолго. Мы видим, что семейство Apple M1 в бенчмарках показывает потрясающие результаты, не хуже флагманских моделей от Intel и AMD, а кое-где и лучше их. Уже выпускаются 128-ядерные серверные ARM, которые ставят рекорды по энергоэффективности, а для серверов это очень важно.

Таким образом, ARM приходит и на десктопы, и на серверы. Но в разработке под архитектуру ARM и при работе с существующим программным обеспечением есть один нюанс. Дело в том, что программирование без блокировок (lock-free) — опасная штука, особенно на этих процессорах. Если на архитектуре x86/x64 сильная модель памяти и здесь инструкции типа store идут в процессор строго по порядку, то в архитектуре ARM это совершенно не факт. В результате частенько случается, что вполне безопасный код x86 порождает состояние гонки под ARM.
Читать дальше →
Total votes 51: ↑46 and ↓5+41
Comments23

Другой взгляд на многопоточность

Reading time7 min
Views22K

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

Читать далее
Total votes 25: ↑24 and ↓1+23
Comments26

Что Go грядущий нам готовит? Разбираем долгожданный релиз 1.19

Reading time8 min
Views18K

Привет всем гоферам! Я пишу на Go уже четыре года — начиная с версии 1.10. Сейчас я занимаюсь разработкой одних из важнейших сервисов в логистике Ozon. 

Не успели мы до конца оправиться от долгожданного релиза Go 1.18 c дженериками, в котором нам предоставили дженерики, как команда Go анонсировала следующий бета-релиз Go 1.19.

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

Навстречу приключениям изменениям!

Подробности под катом
Total votes 58: ↑57 and ↓1+56
Comments5

Какую модель памяти следует использовать в языке Rust?

Reading time10 min
Views9.2K
image

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

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

Тем не менее, я рассчитываю, что мой более чем тридцатилетний опыт работы с конкурентностью и моя работа над моделью памяти в C/C++ (безотносительно memory_order_consume), а также моя роль ведущего специалиста по поддержке модели памяти ядра (LKMM) послужат хорошей отправной точкой, чтобы высказаться о более прозаических задачах, решение которых, я уверен, стремятся поддержать в сообществе Rust.
Читать дальше →
Total votes 31: ↑27 and ↓4+23
Comments3

От стеков к деревьям — новая модель псевдонимов в Rust

Reading time15 min
Views5.8K

С прошлой осени Нивен проходит стажировку, разрабатывая новую модель псевдонимов для Rust: древовидные заимствования (tree borrows). Секундочку, уже слышу, как вы вопрошаете: а разве в Rust ещё нет своей псевдонимной модели? Разве вы, автор, не рассказываете повсюду о «стековых заимствованиях»? Действительно, так и есть, но стековые заимствования — всего лишь один из возможных вариантов реализации для модели псевдонимов, и с этим вариантом есть свои проблемы. Древовидные заимствования призваны учесть опыт, усвоенный при работе со стековыми заимствованиями, и построить новую модель, не такую проблемную. Также при её проектировании принимаются немного иные решения, с учётом некоторых нужных компромиссов и той тонкой настройки, которая, возможно, должна быть привнесена в эти модели, и только потом настанет время решать, какую же из этих моделей принять в Rust в качестве официальной.

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

Для краткости я буду иногда называть стековые заимствования «СЗ», а древовидные заимствования — «ДЗ».

Читать далее
Total votes 21: ↑16 and ↓5+11
Comments8