10. Многопоточность. Программирование на Rust (весна 2019).

Десятая лекция курса «Программирование на Rust» (весна 2019).
Преподаватель - Алексей Александрович Кладов.
Страница лекции на сайте CSC: bit.ly/2PoUXs9
Ссылка на материалы: github.com/matklad/rust-course
Все лекции курса: bit.ly/2QfWama

Пікірлер: 34

  • @deverloperfantom1372
    @deverloperfantom13725 жыл бұрын

    Все четко говорит! Спасибо за информацию, лайк и подписка

  • @luckystrike91
    @luckystrike915 ай бұрын

    мне очень помогло разобраться в атомиках и с memory order видео Crust of Rust: Atomics and Memory Ordering

  • @alexs7931
    @alexs79312 жыл бұрын

    29:50 похоже на EventListener в js. 30:26 Для s можно вызвать Builder, отлично! 1:42:56 По поводу сырых указателей и move в mache.

  • @mascai
    @mascai8 ай бұрын

    39:23 В конце функции мейн не хватает handler.join().unwrap(); или я путаю?

  • @NikBond1000
    @NikBond10004 жыл бұрын

    "Ваша программа - не программа"(с)

  • @wa7sa34cx

    @wa7sa34cx

    2 жыл бұрын

    Тоже понравилось 😆

  • @dmitry.aleksandrov
    @dmitry.aleksandrov4 жыл бұрын

    Спасибо за отличный курс! Но 1:30:29 в предпоследней строчке смените lock() на read() :)

  • @alekseykladov1144

    @alekseykladov1144

    3 жыл бұрын

    Ога, хорошаее замечание. На самом деле, можно ещё лучше -- позвать get_mut, который требует &mut RwLock и **не** захватывает сам лок. Те, мы тут статически понимаем, что у нас есть эксклюзивный доступ к мьютексу, и можем безопасно достать из него данные безо всякой синхронизации. Магия! doc.rust-lang.org/std/sync/struct.RwLock.html#method.get_mut

  • @luna_moonspeak
    @luna_moonspeak5 жыл бұрын

    1:20:01 Должно быть "неважно, какой код вы _пишете_", а не "... _пишите_" ))

  • @Archidamus
    @Archidamus5 жыл бұрын

    21:58 Довольно необычно что можно вызывать mem::forget и этот будет ок. Получается на любые гварды, вроде Ref, RefMut из предыдущих лекций можно mem::forget и счетчик RefCell не вернется в нормальное состояние. Впрочем это должно вызвать каких-то проблем, раст как я понял считает что утечка - это ок (safe). Наверное у языка была возможность сделать mem::forget unsafe, как я понял он реализован через #[lang = "manually_drop"] - т.е. на уровне языка, а не каким-то safe кодом.

  • @KaraMaslyatam

    @KaraMaslyatam

    5 жыл бұрын

    Можно руками без unsafe утечь память через циклический список, про это будет дальше - kzread.info/dash/bejne/dWF20rWwirLUfqg.html Используешь interior mutability контейнеры - сам себе злобный Буратино и нужно следить за циклическими структурами, быть готовым словить в рантайме панику или зависнуть в дедлоке.

  • @KirillLykov
    @KirillLykov2 жыл бұрын

    про существенно дороже атомарные операции -- на x86 atomic_add будет 60 циклов то есть в 15 раз как минимум дороже чем обычный

  • @KirillLykov
    @KirillLykov2 жыл бұрын

    И такой курс (про потоки синхронизацию модели памяти) есть -- kzread.info/dash/bejne/ZWqAr8x6dsWslso.html Источник неоднозначности это не только компилятор но и неопределенный порядок исполнения инструкций процессором

  • @grachev330
    @grachev3305 жыл бұрын

    А в примере на 55:00 точно будет гонка? Мы же явно делаем join, счетчик на главном потоке будет увеличиваться до старта заспавненного потока, и уменьшаться уже после его завершения (drop Rc на главном потоке вызовется уже после join)

  • @KaraMaslyatam

    @KaraMaslyatam

    5 жыл бұрын

    Это так выглядит со стороны алгоритма. Компилятор может вообще не инкрементить счётчик (если мы не используем его значение явно) или инкрементить его после создания потока. Может быть как угодно, это UB. Если у потоков есть общая изменяемая память, необходимо использовать атомарные типы. Надо запомнить раз и навсегда: не будешь синхронизировать потоки - получишь UB (если пишешь unsafe Rust или С/C++ код).

  • @alekseykladov1144

    @alekseykladov1144

    5 жыл бұрын

    Кстати, да, действительно, тут гонки данных быть не должно, потому что join это точка синхронизации, спасибо! Привыка joinить треды помешала сделать правильный пример :-) Так что, в данном случае, компилятор запрешает этот код консервативно, но понятно что небольшая модификация (например, ещё один Rc::clone перед join) может легко привести к UB.

  • @lizzienovigot
    @lizzienovigot Жыл бұрын

    Блин долго я думал кого мне лектор напоминает... это же Фред и / или Джордж Уизли! Шалость удалась.

  • @prigl4548
    @prigl45483 жыл бұрын

    От меня ускользает понимание, зачем в API атомиков есть методы с memory order. Когда реально требуется memory order выше relaxed, гарантиями, которое это дает по happens-before, кажется, можно воспользоваться только в блоке unsafe. Т. е. в этом месте смешиваются API для «прикладного» и «системного» программирования. И для «прикладного» программирования без unsafe можно ошибочно указывать избыточный memory order просто от непонимания и потенциально ухудшить производительность на некоторых архитектурах. Как в примере со счетчиком в лекции, где sequential consistency для просто инкремента избыточно.

  • @alekseykladov1144

    @alekseykladov1144

    3 жыл бұрын

    Да, это верное наблюдение. В целом конечно можно придумать вырожденный пример на атомиках, где и без unsafe можно пронаблюдать memory orderings, но в реальном коде такого не возникает. Гипотетически, можно было бы придумать "простое" апи атомиков, где всё Relaxed, и сложное, с Ordering. Но тогда пришлось бы тащить два API. Тут ситуация похожа на сырые указатели, которы можно получать в safe code, но с которыми там ничего интересного не сделаешь. Отдельно согласен про инкремент. Я раньше придерживался популярной позиции, что надо по умолчанию делать SeqCst, и менять, только если бенчи показывают, что надо. Сейчас думаю, что это плохая стратегия, и что надо ставить минимально возможный Ordering, потому что так проще понять код. Иными словами, если ты не можешь объяснить, что код с `Relaxed` работает корректно, то ты тем более не сможешь объяснить, почему `SeqCst` работает. `SeqCst` добавит в теорему дополнительных, сложных и ненужных, условий, и сделает доказательство непонятнее.

  • @flashmozzg
    @flashmozzg5 жыл бұрын

    1:22:35 А как же системы, где нет 8-байтовых атомиков?

  • @KaraMaslyatam

    @KaraMaslyatam

    5 жыл бұрын

    Spinlock. Но это не про Rust, и даже не про LLVM (именно в таком случае как минимум на x86), а про выбор "сишной" реализации под каждую платформу. А вообще, меньше знаешь - крепче спишь.

  • @flashmozzg

    @flashmozzg

    5 жыл бұрын

    @@KaraMaslyatam Ну я к тому, что никаких доп. гарантий нет. По крайней мере по сравнению с C++. Поддерживается архитектурой - будет нативный атомик, иначе лок/мьютекс. Никакой магии.

  • @user-sp9jq3ee7z

    @user-sp9jq3ee7z

    5 жыл бұрын

    На таких системах не будут работать типы AtomicU64 и AtomicI64. Максимально переносимые типы - это AtomicUsize и AtomicIsize, но и они не будут работать на тех платформах, где атомики не поддерживаются вообще.

  • @flashmozzg

    @flashmozzg

    5 жыл бұрын

    @@user-sp9jq3ee7z Да, посмотрел в доку. Там системах, где не поддерживаться просто не будут определены типы.

  • @yazvit
    @yazvit3 жыл бұрын

    Так данные пересекаются, кеш линии же есть - 4 инта вплотную друг к другу :) 41:00

  • @ihorrudynskyi466

    @ihorrudynskyi466

    3 жыл бұрын

    И что с того? Можно писать в 1 кеш линию с разных потоков хоть это и медленно из-за синхронизации. Код на слайде всегда напечатает единицы. на 44:00 лектор все обьясняет.

  • @stIncMale

    @stIncMale

    Жыл бұрын

    Это называется false sharing, он может негативно влиять на производительность, но не на корректность.

  • @KaraMaslyatam
    @KaraMaslyatam5 жыл бұрын

    Зачем ".rodata" секции права на исполнение? Ведь Rust знает, что эти данные не надо исполнять. А любителям непортабельного unsafe кода можно дать какой-нибудь аттрибут типа #[derive(ExecutableAndVeryUnsafe)] и мержить это добро в ".text". А так никакого смысла в отдельной секции нет и вроде как где-то всё мержится в ".text" (логично).

  • @KaraMaslyatam

    @KaraMaslyatam

    5 жыл бұрын

    Понятно. Это оптимизация линковщиков, которым плевать, что ты там хочешь отдельный "R--" сегмент памяти, схаваешь и "R-X" - нечего отнимать драгоценные дескрипторы и делать лишний вызов. Расчёт на то, что в рид-онли секции исполняемого файла не может быть ничего настолько исполняемого, чтобы сделать что-то плохое (жуткое заблуждение).

  • @flashmozzg

    @flashmozzg

    5 жыл бұрын

    Все эти .rodata, .text и т.д., это уже не к Rust-у вопросы, а к ОС/ABI. Это к тому, что "Ведь Rust знает, что эти данные не надо исполнять". - знать то он знает, но на то, как в target системе реализованы exe-шники он повлиять не может.

  • @sergeysergeev1132
    @sergeysergeev1132 Жыл бұрын

    Все классно, но эти эканья и причмокивания каждые 3 секунды просто пытка(

Келесі