![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
http://cppjournal.blogspot.com/
Здесь есть статья про lock_free программирование. Для асинхронного удаления элемента используются весьма сложные конструкции. Я вижу решение таким. Довольно просто, и эффективно. Но, может bыть я что-то недопонимаю, и на самом деле здесь bаги? неbольшой тест LWS
Это сообщение отредактировал(а) Леопольд - 28.11.2010, 01:22 -------------------- вопросов больше чем ответов |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Вроде bы раbотает, даже если сперва запустить потоки, которые выкидывают элементы из стека...
Это сообщение отредактировал(а) Леопольд - 28.11.2010, 01:56 -------------------- вопросов больше чем ответов |
|||
|
||||
| boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
там их несколько. о какой именно идет речь? второе - есть либа relacy. о ней тоже говорится в третьей статье. |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Леопольд
Ну для начала скажу, что тут есть проблемы не только с очисткой памяти, здесь не предусмотрен pop() на пустом стеке. Что касается проблемы очистки памяти, опишу ситуацию. В стеке 10 элементов, 2 потока одновременно выполняют pop().
1 поток выполняет все строчки до 4-ой. Выполняет конструкцию while (!m_head.compare_exchange_weak(old_head, old_head->next)); compare_exchange_weak возвращает false, т.е. ожидается еще одна итерация и поток передает управеление другому потоку 2 поток входит в pop(), выполняет все действия, удаляет head (так-как old_head != &end), возвращает значение и передает управление 1-ому потоку. 1 поток пытается выполнить еще одну итерацию в цикле while (!m_head.compare_exchange_weak(old_head, old_head->next)); но old_head указывает на удаленную область памяти и old_head->next - обращение к ней, что ведет за собой неопределенное поведение. И еще .. пользя от функции size() здесь довольно сомнительная. По сути она возвращает программисту размер, который когда-то точно был размером этого стека, не более. Это сообщение отредактировал(а) azesmcar - 28.11.2010, 07:04 |
|||
|
||||
| boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
||||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Отвлекся..вернемся к делу
http://liveworkspace.org/code/b6e8617b670b...85227a2cb07ea49 всего лишь несколько последовательных запусков и... вообще непонятен смысл этой статической переменной, в ее роли мог бы выступать 0, и не надо было бы проверять при удалении. boostcoder Ну разве что для логирования может сгодиться, другого применения я не вижу
Такой тест придется запускать ни один раз, чтобы проверить работоспособность. Лучше использовать правда придется немного модифицировать код, но эта жертва, на которую стоит пойти Это сообщение отредактировал(а) azesmcar - 28.11.2010, 07:56 |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Это "для сеbя", надо разоbраться с relacy, а это время.
Для этого end и нужна. Она зацикливает конец списка на сеbя. Это сообщение отредактировал(а) Леопольд - 28.11.2010, 11:50 -------------------- вопросов больше чем ответов |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Полегчало? Лучший спосоb разоbраться - сделать свой, возможно уbогий, вариант. Это сообщение отредактировал(а) Леопольд - 28.11.2010, 10:23 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
||||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
поbорол при помощи статического указателя (только это уже не lock_free, а wait_free):
Рельна ли ситуация, когда поток подменил указатель и внезапно умер, не завершив раbоту? Если да, то bудет deadlock. Это сообщение отредактировал(а) Леопольд - 28.11.2010, 23:00 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
А в чем замысел? Почему compare_exchange заменен на if и exchange?
Вообще комментарии бы не помешали, не знаю будет работать или нет, детально не смотрел, но насколько я понял и эта работа в холостую по сути лишает преимущества перед блокировками. дедлока тут по определению быть не может. Дедлок может возникнуть только при блокировании, а тут нет блокирования. Это сообщение отредактировал(а) azesmcar - 30.11.2010, 10:49 |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
compare_exchange сложнее читать, он неинтуитивно записывает новое значение атомарной переменной по ссылке в первый аргумент. Это сообщение отредактировал(а) Леопольд - 28.11.2010, 17:37 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
spin lock - тоже lock, но в user-mode и никак не может быть wait-free. wait-free функция означает, что любой поток, начавший выполнять эту функцию закончит выполнение за N-ое количество шагов, и N никак не зависит от других потоков.
Там слишком мало информации, это всего лишь базовые сведения, если интересует тема могу подкинуть литературу, но только на английском. Это сообщение отредактировал(а) azesmcar - 28.11.2010, 17:22 |
|||
|
||||
| Леопольд |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Не откажусь от ссылок на признанных авторов в данной теме. Спасиbо! Английский даже лучше, иногда перевод тяжелее понять. Добавлено @ 17:35
Это сообщение отредактировал(а) Леопольд - 28.11.2010, 18:07 -------------------- вопросов больше чем ответов |
||||
|
|||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Получается, что compare_exchange тот же spin lock.
-------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Завтра пришлю. Нет, spin-lock - пустая итерация в ожидании, пока другой поток не изменит состояния некой переменной, т.е. это блокировка, mutex работает точно также, просто ожидание не тратит процессорных ресурсов, а compare_exchange ничего не блокирует, он атомарно производит некое действие, никакой другой поток не дожидается его завершения, чтобы продолжить свою работу. Это сообщение отредактировал(а) azesmcar - 28.11.2010, 21:03 |
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
||||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
||||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Я, конечно, имел ввиду в цикле. Если, груbо говоря, 300 процессов bудут постоянно менять переменную, кто-то из них может начать голодать.
Здесь за флажок принимается не какое-то, заранее определённое значение, а смена значения. Если не изменилось, то поменять, но только один процесс сможет это сделать. Остальные, перейдут на следующую итерацию.
Получается, что если spin lock затрагивает такое же количество тактов, то производительность не упадёт, и шансы на голодание останутся на том же уровне. Это сообщение отредактировал(а) Леопольд - 28.11.2010, 22:44 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Это не делает из любой итерации блокировку. Эта итерация не блокирует другие потоки, как это делает spin lock, но количество итераций все таки зависит от того, что делают другие потоки, потому эта функция не wait-free. Статьи эта статья на русском, не помешает ознакомиться Что такое модель памяти? немного википедии http://en.wikipedia.org/wiki/Non-blocking_algorithm и далее все на языке Шекспира Herb Sutter - Lock-Free Code: A False Sense of Security Andrei Alexandrescu - Lock-Free Data Structures Andrei Alexandrescu, Maged Michael - Lock-Free Data Structures with Hazard Pointers Thomas Edward Hart Thesis Maged Michael - Hazard Pointers Herb Sutter - A Principle-Based Sequential Memory Model for Microsoft Native Code Platforms Geoff Langdale - Lock-Free programming ABA problem Это сообщение отредактировал(а) azesmcar - 29.11.2010, 08:43 |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
azesmcar, премного благодарен!
-------------------- вопросов больше чем ответов |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
На spin lock'е при вытесняющей (preemptive) многозадачности, очень легко dead lock получить. Когда процесс с более низким приоритетом был прерван сразу после того, как он сделал spin lock. В lock free это невозможная ситуация. Это сообщение отредактировал(а) Леопольд - 30.11.2010, 09:59 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
||||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
azesmcar, ясно, спасибо.
-------------------- вопросов больше чем ответов |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
deleted
Это сообщение отредактировал(а) Леопольд - 30.11.2010, 23:09 -------------------- вопросов больше чем ответов |
|||
|
||||
| Леопольд |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Не могу скачать relacy...
Надеялся она мне поможет понять почему это не работает. Пытаюсь написать вариант с очередью на удаление (end зациклен на себя):
Это сообщение отредактировал(а) Леопольд - 1.12.2010, 11:12 -------------------- вопросов больше чем ответов |
||||
|
|||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
На гугле запретили выкладывать zip файлы. Качать надо отсюда, добавлю в статью. http://sites.google.com/site/1024cores/downloads |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
azesmcar, спасибо!
Так вроде работает, теперь надо с relacy попробовать протестить.
Не, нифига, здесь утечка памяти... Это сообщение отредактировал(а) Леопольд - 1.12.2010, 11:32 -------------------- вопросов больше чем ответов |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
relacy не помог...
http://liveworkspace.org/code/8ed457a04766...847bee388deb79b
запустил на ночь, для 200000 операций push/pop параллельно. Это сообщение отредактировал(а) Леопольд - 1.12.2010, 23:07 -------------------- вопросов больше чем ответов |
|||
|
||||
| boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
где? на LWS ?! Добавлено через 1 минуту и 24 секунды и relacy на LWS нет. хотя подумываю установить. карман ведь не тянет Добавлено через 2 минуты и 48 секунд Леопольд, скажи, у тебя есть где реально применить сие? |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Нет конечно, локально.
Уменьшил до 200000, bоюсь к утру LIVELOCK напишет иначе... Добавлено @ 23:11 Пока нет. Просто проbую свои силы. Потом хеш-таbлицу хочу написать и распараллелить A* Статью Тиграна прочёл и, неожиданно увлёкся. Кажется мне что в ИИ, bудущее за lock free алгоритмами. Это сообщение отредактировал(а) Леопольд - 1.12.2010, 23:14 -------------------- вопросов больше чем ответов |
|||
|
||||
| boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 49 Всего: 110 |
установил relacy.
вот тест: http://liveworkspace.org/code/08782ad50b2d...3c7ef1f00810096 Добавлено @ 23:24 только не понимаю что там выводится, и что должно выводится Это сообщение отредактировал(а) boostcoder - 1.12.2010, 23:25 |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
чем именно он должен был помочь? если нужно куда-то применить, советую взглянуть на libcds О! Отлично. Леопольд Александреску в одной из статей использует такой трюк. Инкапсулируется некий тип (например map) Чтение - wait-free безо всяких итераций, просто возвращение объекта. Запись - создание копии, добавление новой записи и замена внутреннего объекта. Ну и конечно же опять встает вопрос удаления старой копии. Это можно построить на шаблоне и применять эту технику для любого типа, но естественно, это эффективно только тогда, когда запись является редким явлением. Упор делается на скорость чтения высокая. Это сообщение отредактировал(а) azesmcar - 1.12.2010, 23:43 |
|||
|
||||
| Леопольд |
|
||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Добавлено @ 06:46 Где-то, видимо двойной delete. Не могу понять где... Мне, вроде бы, удалось обойти добавление эелементов обратно в очередь на удаление. Это может сильно поднять производительность. http://liveworkspace.org/code/8ed457a04766...847bee388deb79b
Добавлено @ 06:49 Поток не успел завершить раbоту до достижения
Это сообщение отредактировал(а) Леопольд - 2.12.2010, 09:11 -------------------- вопросов больше чем ответов |
||||||
|
|||||||
| azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Этого не знаю... |
||||
|
|||||
| Леопольд |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Оно, кстати, иногда работает, хотя нагрузка серьёзная. Два потока "выкидывают" элементы другие два "вставляют", в сумме 2000000 элементов.
http://liveworkspace.org/code/705bf2998c43...9a3bced3e591522 Сперва пытался сделать вариант с возвратом элементов обратно. Но он просто "вешался" под такой нагрузкой. Может я как-то неправильно тестирую? Не получается воспроизвести...
Это сообщение отредактировал(а) Леопольд - 2.12.2010, 11:45 -------------------- вопросов больше чем ответов |
||||
|
|||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Леопольд
Добавь хоть комментарии и опиши алгоритм. |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Он похож на тот, который в статье. Основное отличие, работа с очередью удалённых - m_deleted_head:
1. Загружаю m_deleted_head (указатель на начало очереди на удаление) 2. умешьшаю счётчик потоков и если он стал равен нулю (значит нет потоков, которые работают с тем же m_head - указатель на "выкидываемый" элемент). 3. пытаюсь сделать один strong CAS указателя m_deleted_head и зацикленного на себя указателя &end (признак конца очереди). Рассчёт на то, что если удалось подменить m_deleted_head с первого раза, значит ни один поток не успел его поменять и список можно спокойно удалять. Если не удалось подменить, то пихаю удаляемый элемент в очередь на удаление. Ещё, возможно, одно отличие (точно не уверен, может в статье так же). Попытка освободить ненужную занятую память происходит каждый раз, даже если сам стек оказался пустым. накидал это в виде комментариев в предыдущий пост http://forum.vingrad.ru/act-ST/f-92/t-3162.../p-2258093.html Это сообщение отредактировал(а) Леопольд - 2.12.2010, 11:37 -------------------- вопросов больше чем ответов |
|||
|
||||
| Леопольд |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Заработало!
8000000 элементов, 4 потока: 2 удаляют, 2 добавляют. http://liveworkspace.org/code/a1e0bde56b2e...720510a50a6379c relacy тоже удовлетворён...
Если всего 2 потока удаляют то, average length of non deleted queues = 0.09. P.S. Пожалуй этот вариант уже не так "убог"... P.S.S А вообще, очень даже ничего! Это сообщение отредактировал(а) Леопольд - 2.12.2010, 15:06 -------------------- вопросов больше чем ответов |
||||
|
|||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
блин
на одноядерном процессоре, почти сразу. бага "прибил". Всё чудесно! Если кто-то сможет его "уронить", буду весьма признателен. Это сообщение отредактировал(а) Леопольд - 2.12.2010, 15:09 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Леопольд
Сколько всего изменилось Мало того, что нашел..так еще и прибил ага, посмотрю. Добавь в relacy количество потоков и итераций и оставь на ночь. |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Плохо приbил...
http://liveworkspace.org/code/1d1704acbdea...fc11a835f900d4e -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Леопольд
Я бы хорошенько пересмотрел этот код. Это и так сложно, а у тебя усложнено еще больше. Комментарии нужны в первую очередь для себя, раздели все на мелкие функции, это заметно облегчит и чтение и понимание того, что происходит. Представить в уме возможные варианты выполнения для нескольких потоков, которые в любой момент могут делать все, что угодно и так сложно, а это еще усложняется кодом. Для начала напиши список, который работает, но с утечками, протестируй, а потом добавляй очистку памяти отдельными функциями. Отдели как нибудь ту часть, которая потенциально может содержать ошибку (т.е. часть очистки памяти) от той, которая протестирована и работает. На данный момент код функции pop слишком большой, чтобы можно было найти в нем ошибку. |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
azesmcar, пытаюсь рафинировать, потихоньку...
И прихожу к вывод что нельзя использовать обычную связку malloc/free Запускаю два потока, один добавляет, другой удаляет. Между собой у них только одна атомарная переменная (указатель на голову стека), relacy тесты проходят с опцией (p.search_type = rl::fair_full_search_scheduler_type;) которая всё пространство состояний тестирует. Всё ок. Но, как только пытаюсь запустить на одноядерной машине (Ubuntu 10.04, g++ 4.5.1):
Сейчас соображу спин лок на выделение памяти и проверю. Google говорит что есть такая штука как lock free malloc Это сообщение отредактировал(а) Леопольд - 3.12.2010, 11:36 -------------------- вопросов больше чем ответов |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Вот рафинированный код.
LWS relacy
Не получается уронить (если не увеличивать количество потоков), видимо на сервере несколько ядер: http://liveworkspace.org/code/260469bbd4f7...d03e4ad1d4b26e7 на работа одноядерная машина, на ней падает почти сразу. Это сообщение отредактировал(а) Леопольд - 4.12.2010, 08:24 -------------------- вопросов больше чем ответов |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
С таким спин локом, тоже падает...
Может я зря грешу на malloc/free? P.S. Временами, relacy на спин локе зависает наглухо... P.P.S Пока malloc не отработает, память в список не записывается. Но он может быть вызван до того, как free закончит работать (а может ещё операционка что-то делает с ОЗУ?). Что ж, это за зверь такой: "lock free malloc"? Это сообщение отредактировал(а) Леопольд - 3.12.2010, 11:39 -------------------- вопросов больше чем ответов |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Очевидно что отдельно от push, pop отрабатывает нормально:
сперва забиваю стек (10 миллионов элементов), потом 100 потоков начинают дёргать pop что радует, когда последний поток закончил работать, вся память полностью освободилась (в отличие от предыдущих "кривоногих" версий). Шанс получить "хвост" в конце работы всех потоков пренебрежительно мал. И чем больше потоков, тем меньше шансов. Самый невезучий подчищает за всеми. http://liveworkspace.org/code/1d76fb72fafa...af5403f5ae0b02e На одноядерной (Ubuntu 10.04 g++4.5.1) тоже работает без сбоев. Тут вывод поинтереснее: http://liveworkspace.org/code/81347b6f4ba2...09c75a0fbcc31a5
Это сообщение отредактировал(а) Леопольд - 3.12.2010, 14:19 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Леопольд
Добавил немного комментариев, теперь давай прочитаем код
начнем со строки 24. тут ты сперва проверяешь, что это единственный поток в функции pop (кстати все время хочу спросить почему value - 1 == 0 а не value == 1?). потом проверяешь, что никто не менял m_deleted_head и он все еще равен head-у, т.е. поменять может в том случае, если в этом промежутке создался другой поток. дальше, если ничего менялось ты удаляешь все элементы. Вот тут то и проблема. Представь, что 1 твой поток дошел до строки 33, удали элемент, на который на данный момент указывает m_deleted_head (так как m_deleted_head и head указывают на ту же область памяти) и передал управление второму, который пытается добавить следующий элемент в список на удаление, но натыкается на UB на строке 20. В примере я не зря очищал m_deleted_head и отделял от него весь список в локальный указатель, это делалось для того, чтобы другой поток в это время не смог с ним работать. |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Это сообщение отредактировал(а) Леопольд - 3.12.2010, 14:25 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Ты забываешь, что это две разные проверки и они НЕ атомарны. Потому я и отделил их в два отдельных if-а, чтобы было нагляднее. Возможна такая ситуация: первая проверка выполняется, перед началом выполнения второй, другой поток входит в функцию pop. Добавлено через 1 минуту и 56 секунд
Это сообщение отредактировал(а) azesmcar - 3.12.2010, 14:25 |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Не, про это я уже не забываю.
Здесь проблема появляется когда параллельно начинаешь запихивать элементы в стек. Можно и сильнее нагрузить, результать будет тот же. 100 потоков удаляют 10000000 элементов из стека размером 100000001 элементов: http://liveworkspace.org/code/81347b6f4ba2...09c75a0fbcc31a5
Это сообщение отредактировал(а) Леопольд - 3.12.2010, 14:43 -------------------- вопросов больше чем ответов |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Я пытался найти способ ответвить один поток в своё русло при помощи одного только стчётчика, но так и не смог. Но тут помогла compare_exchange_strong на m_deleted_head. Тот, кто смог её выполинть, гарантированно владеет списком указателей, с которыми больше никто не работает. Поэтому вся работа с указателями происходит до того как уменьшается счётчик. Я и имя ему такое дал, что бы с гонками ассоциировалось. Чистит хвосты самый нерадивый. Это, кстати, наглядно из логов видно (пару постов назад) Это сообщение отредактировал(а) Леопольд - 3.12.2010, 14:58 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Леопольд
Да, это я напутал..ты тоже тут выделяешь список в отдельную переменную, но проблема все равно та же. процитирую статью
описываю проблемную ситуацию, номера строк смотри в моем коде. 1-ый поток входит в pop 2-ой поток входит в pop 3-ий поток входит в pop 1-ый поток продолжает выполнение и доходит до строки 27, так-как остальные два потока пока не инкрементировали значение счетчика 2-ой поток начинает выполнение и доходит до строки 10 3-ий поток начинает выполнение и доходит до строки 10 2-ой поток удаляет элемент из списка и дойдя до строки 20 помещает его в список на удаление 1-ый поток продолжает работу и выделяет список в локальную переменную m_deleted_head 1-ый поток доходит до цикла на строке 30 и начинает удалять элементы, включая тот, который туда поместил 2-ой поток 3-ий поток просыпается и все еще ссылается на тот элемент, который поместил в список на удаление 2-ой поток 3-ий поток при попытке выполнить 10-ую строку вылетит с ошибкой в двух словах: один поток удаляет объект, помещенный в список другим поток, на который ссылается третий. Это сообщение отредактировал(а) azesmcar - 3.12.2010, 15:06 |
||||
|
|||||
| Леопольд |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Вообще, relacy классная штука. Я когда первый вариант ему подсунул, он тут же показал что память течёт рекой... Добавлено @ 15:31 Вариант из статьи форсирует алгоритм "гулять" по очереди туда-обратно. К тому же, он вставляет очередь обратно по одномоу элементу, постоянно мешая другим потокам, что очень негативно сказывается на производительности. С 10 миллионами элементов он будет работать очень долго. Сперва я пытался сделать что-бы он вставлял обратно очередь сразу всю целиком, но всё равно приходилось "гулять" из конца в конец. Именно поэтому, я решил попробовать сделать иначе. Обойти этот момент. Похоже удалось. Но возникает какая-то загадочная проблема с выделением и освобождением памяти параллельно. Это сообщение отредактировал(а) Леопольд - 3.12.2010, 15:36 -------------------- вопросов больше чем ответов |
||||
|
|||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Да, верно..невнимательный я что-то, не обратил внимания на if. А тут точно есть проблема в функции pop? Я ничего другого не вижу, вроде все в порядке. |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Похоже что нет. Я пришёл к мнению что с pop всё ОК. Пробовал под большой нагрузкой и relacy всё проверил.
Это сообщение отредактировал(а) Леопольд - 3.12.2010, 15:38 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
||||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Надо несколько потоков запустить. Половина вставляет элементы, другая половина выкидывает. При большом количестве потоков и элементов.
P.S. пора домой... Это сообщение отредактировал(а) Леопольд - 3.12.2010, 15:40 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Леопольд,
я теряюсь в твоих исходниках, уже не понимаю которая версия правильная, которая нет..покажи пальцем где и когда происходит. |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Леопольд
А у тебя там случайно не bad_alloc вылетает? |
|||
|
||||
| Леопольд |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
http://forum.vingrad.ru/act-ST/f-92/t-3162.../p-2258868.html здесь она же, но bез relacy модификаций http://liveworkspace.org/code/81347b6f4ba2...09c75a0fbcc31a5 Добавлено @ 18:54 bыло bы неплохо
Вот, уронил (2 потока вставляют, 2 выкидывают): http://liveworkspace.org/code/34a83f493245...44fb349a193814d Это сообщение отредактировал(а) Леопольд - 4.12.2010, 09:01 -------------------- вопросов больше чем ответов |
||||
|
|||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Подумал что можно попроbовать аллокатор написать. В lock free это, наверное, очень сложная штука (а может просто нереальная). Память фрагментируется совершенно непредсказуемо. Может в этом и проbлема...
Решил попроbовать malloc из libatomic-ops-dev http://manpages.ubuntu.com/manpages/lucid/...c-malloc.3.html Отпишусь, когда bудут результаты. судя по описанию, не подходит Попроbую почитать это когда время bудет (автор Maged M. Michael).
Это сообщение отредактировал(а) Леопольд - 4.12.2010, 10:10 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
||||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Леопольд
Был в небольшом отпуске..вернемся к нашим баранам, на свежую голову и думается легче. Проблема то лежит на самом видном месте Проверка
Эквивалентна проверке
Но почему тут проверяется на единицу? При входе в pop значение инкрементируется 1 раз, а тут декрементируется (тоже один раз). Т.е. После операции fetch_sub(1) переменная указывает на количество потоков в функции pop на данный момент (не считая текущего потока). А значит проверка на 1 означает, что там есть еще один поток, который может создать проблемы Исправлять естественно вот так
|
||||||
|
|||||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
azesmcar, fetch_sub возвращает предыдущее значение. Т.е. 1 в данном случае. Если только тут где-то ABA спряталась. Но я не вижу.
Скорее всего, проbлема в аллокации памяти. По отдельности push и pop выполняются bез нареканий, но если смешать... Везде пишут что стандартные malloc и free раbотают на мьютексе. Это сообщение отредактировал(а) Леопольд - 8.12.2010, 19:39 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Да? Не помню..посмотрел в документации, действительно так и есть.. Там не может быть проблем, в мире полно работающих структур с использованием операторов new и delete. Проблема как я уже говорил в обращении к удаленному участку памяти, надо просто ее найти. Добавлено через 59 секунд каким образом это может помешать работать алгоритму? Это может сказаться на производительности, это может лишить структуру статуса lock-free, но никак не должно мешать ей работать правильно. |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Согласен, алгоритм просто перестаёт bыть lock free. Вероятнее всего, проbлема во фрагментации памяти. Если выделять память bлоками одинакового размера, то перестаёт падать: http://liveworkspace.org/code/3e95623f8da7...1b146a08dd3a6e7 Это сообщение отредактировал(а) Леопольд - 8.12.2010, 19:43 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
||||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Леопольд
Провел несколько тестов. Что-то здесь не так.. Добавлено через 1 минуту и 22 секунды имеется ввиду на gcc 4.5, к сожалению другой библиотеки для тестов у меня нет. |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Леопольд
Нашел..в общем аллокатор тут не причем, точнее причем, но не он источник проблемы. Это ABA Поигрался с алокатором, в итоге
практически всегда выводит одно и тоже, т.е. если запрашивать память после удаления, системный аллокатор скорее всего вернет ту же область памяти, которую недавно освободил. Это прекрасно объясняет почему разделение push и pop избавляют от проблемы а также то, почему без delete -а все работает - аллокатор не может вернуть старый адрес, так-как тот еще не освобожден. Позже попробую исправить. Это сообщение отредактировал(а) azesmcar - 9.12.2010, 09:52 |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
К сожалению далеко не все еще реализовано в GCC
пробую исправить добавлением счетчика-а, но std::atomic<used-defined-type> еще не реализован.
идея в том, чтобы инкрементировать значение счетчика, тем самым делая указатели на тот же участок памяти разным в разное время. DCAS по идее должен быть Lock-free на всех современных платформах. Это сообщение отредактировал(а) azesmcar - 9.12.2010, 10:38 |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Если я правильно понял, то мьютекс здесь смог бы помочь. А вот по поводу ABA, это, наверное оно самое! Надо понять только как Это сообщение отредактировал(а) Леопольд - 9.12.2010, 11:01 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Посмотри этот пример
выделяется память, возвращается адрес память освобождается и при следующем выделение памяти аллокатор снова возвращает тот же самый указатель, т.е. выделяет память на том же участке. Тут и возникает ABA, CAS думает, что это тот же указатель, а он другой. В качестве решения можно как-то уникально идентифицировать каждую аллокацию используя счетчик, но тут сложность с реализацией (писал выше об этом). Можно сделать через std::atomic<long long> - его размер 8 байтов, туда можно поместить и счетчик и указатель. Не сильно переносимо конечно, но для теста сойдет Не понял причем тут мутекс? Это уже блокировка, мы про неблокирующие алгоритмы говорим. Это сообщение отредактировал(а) azesmcar - 9.12.2010, 11:09 |
||||
|
|||||
| Леопольд |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Это я понял. Я про то предложение, которое процитировал.
Может ли один и тот же адрес попасть в стек дважды? После чего дважды перекочует в очередь на удаление. По моему, тоже нет, по той же причине. Не могу понять, где здесь ABA. Но оно вероятнее чем баги в gcc. У меня, кстати, тоже только gcc 4.5.1 под рукой, и на работе и дома.
Можно попробовать проверить, надо добавить std::set<void *> и блокировки при работе с ним. Выделил память, запихнул туда адрес, если он уже там, значит ABA имеет место быть. Освободил память, выкинул адрес из сета. Только вот получится ли воспроизвести ошибку? Блокировка может сделать так, что ошибка пропадёт навсегда. P.S. на работе сроки поджимают, буду сюда заглядывать, но гораздо реже чем раньше. Это сообщение отредактировал(а) Леопольд - 9.12.2010, 12:06 -------------------- вопросов больше чем ответов |
||||
|
|||||
| azesmcar |
|
||||||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Леопольд
Проблема та, которую я описывал еще в первом или во втором предположении Вот код
Представь, что 1 поток останавливается на выполнении строки
к этому моменту количество потоков в функции pop уже декрементировано и равно 0. до того, как произойдет сравнение другой поток может изменить этот список, на что ты вполне логично ответил
т.е. если кто-то изменял список, то проверка
не пройдет. это верно, разве что, если другой поток не изменил этот список, в конце добавив туда элемент с тем же адресом представь, что твой код остановился на выполнении этой проверки, в head загужен узел A, а потом другой поток удалил несколько элементов, очистил за ними память, добавил еще один, удалил, и последний удаленный имеет тот же адрес, который на данный момент загружен в head в твоем первом потоке. Это возможно, так-как когда твой первый поток остановится на выполнении проверки, счетчик равен нулю, твой узел (A) в списке to_be_deleted и другой поток волен удалить этот элемент. Вроде бы так..надо подумать еще раз попозже, на свежую голову Это сообщение отредактировал(а) azesmcar - 9.12.2010, 16:25 |
||||||||
|
|||||||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Наверное, это оно. Попроbую оbойти...
Это сообщение отредактировал(а) Леопольд - 9.12.2010, 19:05 -------------------- вопросов больше чем ответов |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Да уж. При помощи одной только CAS не получается оbойти ABA, только если опять же вставлять очередь оbратно. LL/SC могло bы спасти.
-------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
Надо добавить счетчик, но std::atomic для пользовательских типов не реализован, можно через std::atomic<long long>, в первых 4-х байтах хранить адрес, в остальных четырех счетчик. Добавлено через 2 минуты и 17 секунд или надо алгоритм составить так, чтобы проблемы не возникало. |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Это только для 32 битных платформ сойдёт.
Придётся. В общем, мало одной только CAS. Надо бы ещё и LL/SC на всех архитектурах реализовать. Или нужен сборщик мусора. Вроде как хотят его добавить в С++... Это сообщение отредактировал(а) Леопольд - 10.12.2010, 11:24 -------------------- вопросов больше чем ответов |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
deleted
Это сообщение отредактировал(а) Леопольд - 10.12.2010, 11:40 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
||||
|
||||
| azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
http://herbsutter.com/2007/11/01/trip-repo...ndards-meeting/ |
|||
|
||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Зато там довольно накладная очистка памяти, которая может свести на нет всю предполагаемую выгоду от lock free. В невытесняющей многозадачности, при определённой нагрузке, спин лок bудет гораздо bыстрее. Вот если bы везде bыла доступна связка LL/SC или DСAS, а лучше и то и другое и третье.
Иначе это как программировать GUI имея в арсенале только bинарные операции. Ничего удивительного что для двусвязного списка не придумали алгоритм, недостаточно доступных средств. В оbщем, надо подождать... Про сbорщик мусора, видимо, здесь на глаза попадалось. http://www2.research.att.com/~bs/C++0xFAQ.html#gc-abi Это сообщение отредактировал(а) Леопольд - 10.12.2010, 22:40 -------------------- вопросов больше чем ответов |
|||
|
||||
| azesmcar |
|
||||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 81 Всего: 211 |
в твоем варианте тоже, вся проблема в том, что очистка происходит только тогда, когда в функции pop нет других потоков, что в случае высокой нагрузки маловероятно. Альтернатива есть, но решение не такое простое. Почитай у Maged Michael-а про Hazard Pointers.
все только начинается... Это сообщение отредактировал(а) azesmcar - 10.12.2010, 23:16 |
||||
|
|||||
| Леопольд |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 943 Регистрация: 17.6.2009 Репутация: 10 Всего: 13 |
Я пытался обойти тот момент, когда очередь полностью обходится только для того, что-бы поместить все элементы обратно. Если бы под рукой оказались ll/SC то могло получиться.
-------------------- вопросов больше чем ответов |
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |