На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (6) « Первая ... 2 3 [4] 5 6  все  ( Перейти к последнему сообщению )  
> Распараллеливание выполнения без блокировок
    А пока людям, которые думают, что классический подход к многопоточности устарел, предлагаю просветиться вот тут. Очень занятное чтиво. Будет чем пока заняться.
    Сообщение отредактировано: Qraizer -
      Цитата OpenGL @
      Цитата JoeUser @
      Мусье, а вы бы мне могли обосновать необходимость блокировки, где и без нее можно обойтись?

      Звучит примерно как "обоснуй необходимость компилятора, ведь можно в hex кодах всё написать". Можно, конечно, просто это сложно. lock free алгоритмы в разы более сложные в написании и отладке, да ещё и далеко не всегда они работают быстрее (по-моему очередь и стек так вообще часто медленней оказываются, чем с блокировкой), так что в данном случае всё наоборот - ты должен обосновать необходимость реализовывать с lock-free. У тебя есть замеры времени в реальных условиях, из которых следует, что ты много времени тратишь на на ожидания в мьютексах? Или может быть твоя основная цель это научиться работать с lock-free? Если ответа на оба вопроса "нет", то твоё решение менее рационально, чем решение с блокировками.

      Нет. Я тоже, к примеру, не буду оборачивать в смарт какой-нибудь поинтер на что-либо, который всего лишь нужно передать куда-то в legacy API как константу. Если что-то можно сделать просто, это нужно делать просто. В hex набирать программу всегда непросто... хотя бывают гурманы.

      Добавлено
      Цитата Wound @
      OpenGL, ты мне помнится доказывал что в С++ утечек нет. Узри:
      Цитата Wound @
      Node<T>* const NewNode = new Node<T>(iData); //! <<< Выделение памяти

      И где этот хваленный RAII ? И вот такого кода тонны по всюду.
      У него в Попе стэка или в том же пуше, после выделения памяти произойдет исключение - и утечка ресурса гарантирована.

      Создание объекта new гарантирует отсутствие утечек. Операции с атомиками там бессбойные. Операции с сырым поинтером бессбойные. Проблем не ожидается.
      Сообщение отредактировано: Qraizer -
        Цитата Qraizer @
        Создание объекта new гарантирует отсутствие утечек. Операции с атомиками там бессбойные. Операции с сырым поинтером бессбойные. Проблем не ожидается.

        Сбойные, как минимум в Pop методе, в указателе может быть мусор, из за чего полетит AV при вызове - OldHead>Next

        Добавлено
        И когда это new - гарантировал отсуствие утечек? Память он выделил, а дальше в методе вылазиит исключение - и что это гарантирует отсуствие утечек памяти? В С++ GC завезли или я что то пропустил?
          JoeUser, фрилок очень занятная и полезная штука. Но ты должен понимать, что оно лишь обеспечивает целостность тривиальных операций языка, но никак ничего не охраняет от коллизий. Именно поэтому и придуманы были объекты синхронизации, чтобы будучи реализованными на фрилуках где-то глубоко в своём ядре, дать тебе возможность писать защищённый от коллизий код произвольной сложности. Без них ты сам должен это делать. Захватывать объект, для чего использовать спинлук, и в итоге собрать свой собственный объект. Тот самый, использования которого хотел избежать. Вот у тебя и спрашивают, а зачем оно тебе? Непонятно только, почему таким заумным способом спрашивают. Очень редко бывает, когда достаточно просто атомарно сделать что-то тривиальное. Ну вот у тебя это манипуляция Next, например. Ну ок. А теперь у тебя двусвязный список. А у него два поинтера. Ну-ка представь себе атомарное изменение двух поинтеров. Как ты себе это представишь иначе, кроме как булевый флаг, который спинится на "занят"/"свободен" и под "занят" менять, причём уже без всяких атомиков (хотя и с барьерами). И чем тебе этот флаг не мьютекс тогда? Представь теперь что тебе не надо менять, а надо просто пройти по этому списку. Без подобного булевого флага обойдёшься? Точно? Уверен?
          Использование принципов фрилок сродни "я сам всё знаю и за всем слежу". Есть любители нативных поинтеров или там ручного управления ресурсами. В ряде случаев оно даже бывает оправдано. Главное тут – чуять грань. Попробуй вместо одной нитки у себя в примере завести несколько. Почувствуй т.с. руками, каково это.

          Добавлено
          Цитата Wound @
          И когда это new - гарантировал отсуствие утечек? Память он выделил, а дальше в методе вылазиит исключение - и что это гарантирует отсуствие утечек памяти?
          Да. Если new или даже new[], успешно распределили память, но в конструкторе одного из объектов произошёл бадабум, то все уже сконструированные объекты, как и положено, удаляются и выделенная new или new[] память освобождается.
            Цитата Qraizer @
            Я тоже, к примеру, не буду оборачивать в смарт какой-нибудь поинтер на что-либо, который всего лишь нужно передать куда-то в legacy API как константу.

            Я не понял, к чему этот пример. Речь о том, что ТС предпочёл сложное решение простому при отсутствии хоть каких-либо предпосылок к тому, что сложное окажется эффективнее. Это примерно как писать сортировку вставками, не произведя замеры и не убедившись, что std::sort в данном случае окажется хуже.
              Цитата Qraizer @
              Да. Если new или даже new[], успешно распределили память, но в конструкторе одного из объектов произошёл бадабум, то все уже сконструированные объекты, как и положено, удаляются и выделенная new или new[] память освобождается.

              Вообще-то в его коде другая ситуация. Не та о которой говоришь ты.
                Цитата OpenGL @
                Речь о том, что ТС предпочёл сложное решение простому при отсутствии хоть каких-либо предпосылок к тому, что сложное окажется эффективнее. Это примерно как писать сортировку вставками, не произведя замеры и не убедившись, что std::sort в данном случае окажется хуже.
                Это его дело. Давайте не будем, как любят цитировать по поводу русских форумов, отвечать человеку на не заданные вопросы. Мне понадобился всего абзац чётких фактов вместо трёх страниц вокруг да около, дальше пусть решает сам. И кстати, задача у него действительно пока проста – управление одной переменной.
                  Цитата Qraizer @
                  Это его дело.

                  Я с этим и не спорил изначально. Спросил только, почему не взял/скопипастил известную lock-free библиотеку (мало ли, вдруг не знает её), а с ТЗ и выбранным способом решения пусть сам разбирается. Кто я, в конце-концов, такой, чтобы мешать усложнить ТС себе жизнь? :D Но вот это:
                  Цитата JoeUser @
                  Вот пошла тема!!! Рациональность. Прекрасненько. Тут есть о чем поговорить. Расскажи мне, пожалуйста, как сделать рациональнее!

                  по-моему явно сказало о том, что ТС и о разумности подхода поспорить хочет. Так что всё произошедшее тут это исключительно следствие неумения читать чужие аргументы.
                    Цитата Qraizer @
                    Как минимум не инициализировал FreeStack::Head.

                    Вот. То что я просил. Согласен и исправлю. Но пока не понял почему эта переменная инициализируется нулями. За все попытки запуска ни разу не сбойнуло. Странно. :-?

                    Цитата ЫукпШ @
                    Вставил 2 карт-ридера и скопировал с одной карты на другую.

                    Ну это явно не мой вариант! У меня читаются только карточки с магнитной полосой, вмещающие сотни байт, даже не килобайты. Это примерно тоже самое, если к компу подключить вторую клавиатуру. Можно. Только бессмысленно.

                    Цитата Qraizer @
                    Неперехваченное исключение прибьёт всё приложение. Если это не устраивает, то нужно как-то хендлить.

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

                    Цитата Qraizer @
                    Юзеру с головой достаточно 100мс реакции

                    Я примерно тоже к такой цифре склоняюсь, хотя буду пользовать скорее всего 50мс. Посмотрел по диспетчеру задач - загрузка CPU прогой при 100 и 50 практически равная - доли процента.
                      Цитата OpenGL @
                      неумения читать чужие аргументы

                      Или не умение их писать?
                      Вон пришел Qraizer, без лишних словоблудий нашел и показал косяк (с инициализацией).
                      Вот такое я читать умею и люблю.
                        Цитата Qraizer @
                        А теперь у тебя двусвязный список.

                        Это я понимаю! Есть структуры (мой случай), когда free-lock реализуется просто и на ура. А есть структуры, тот же двусвязный список, где это реализовать невозможно или крайне затруднительно. В моем вопросе - мне просто повезло.
                          Цитата OpenGL @
                          Спросил только, почему не взял/скопипастил известную lock-free библиотеку (мало ли, вдруг не знает её)

                          А нафига? У меня же тривиальнейший случай.

                          Кстати, на счет советов с мьютексами для моего случая - я это воспринимаю примерно так:
                          ExpandedWrap disabled
                            if (а == 1) {
                              // на всякий случай, чтобы уж точно
                              if (а == 1) {
                                b=1;
                                break;
                              }
                            }

                          Можно и так. Только зачем.

                          Добавлено
                          Цитата Wound @
                          И где этот хваленный RAII ?

                          Хваленого RAII нет, но за место возможной утечки - сенкс. Действительно, часть кода не моя,
                          с книжки. И у меня тоже возник вопрос - new есть, а delete нету. Разве только что это не
                          обеспечивается std::shared_ptr :-?
                            А на что тогда, по-твоему, std::shared_ptr<> нужен? Накой кому нужен просто абстрактный счётчик копий?

                            Добавлено
                            Цитата JoeUser @
                            Вот. То что я просил. Согласен и исправлю. Но пока не понял почему эта переменная инициализируется нулями. За все попытки запуска ни разу не сбойнуло. Странно.
                            Ну, тебе на это ещё Wound указал до меня. А так-то атомики без явной инициализации инитятся дефолтом, т.е. никак.
                            Сообщение отредактировано: Qraizer -
                              Цитата JoeUser @
                              Вон пришел Qraizer, без лишних словоблудий нашел и показал косяк (с инициализацией).
                              Вот такое я читать умею и люблю.

                              Угу, конечно, я тебе на этот косяк указал еще раньше. Но ты почему то начал обвинять меня в том, что я строю из себя шибко умного. :-?
                                ExpandedWrap disabled
                                  std::shared_ptr<T> Data;
                                   
                                  Node(T const& iData): Data(std::make_shared<T>(iData)) {  }
                                   
                                  Node<T>* const NewNode = new Node<T>(iData);
                                new выделяет память и конструирует на ней iData. Если что-то пойдёт не так, память освободится. Что может пойти не так? Конструктор Node<T> делает make_shared, который потенциально выделяет память, т.к. конструирует shared_ptr<>. Если что-то пойдёт не так, в частности из-за конструктора копии T aka iData, это проблемы make_shared(), чтобы не допустить утечек. По-любому это будет конструктор Node<T>, так что мимо внимания new сие не пройдёт. Конструктор копии shared_ptr имеет атрибут nothrow, и тем более его имеет перемещающий конструктор, который будет задействован в твоём случае. Что не удивительно ни разу, но убедиться было не лишним.
                                При неуспешном создании NewNode все проблемы локализованы внутри new. После успешного создания NewNode остальные операции nothrow. Откуда утечки?

                                Добавлено
                                Ещё мне не нравится, что твой Pop() может вернуть ошибку посредством пустого shared_ptr. Придётся везде проверки пихать. Но с фрилуком иначе, боюсь, и не получится.

                                Добавлено
                                P.S.
                                Цитата Qraizer @
                                Откуда утечки?
                                Если там намёк на отсутствие деструктора у стека, то это уже другой вопрос.
                                Сообщение отредактировано: Qraizer -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (6) « Первая ... 2 3 [4] 5 6  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0514 ]   [ 17 queries used ]   [ Generated: 18.04.24, 23:25 GMT ]