Название: QAtomicInt vs. QMutex Отправлено: once_again_abc от Сентябрь 09, 2011, 04:43 Что быстрее - обращение к переменной через QMutex.lock/unlock или к переменной типа QAtomicInt через testAndSetRelaxed?
Название: Re: QAtomicInt vs. QMutex Отправлено: brankovic от Сентябрь 09, 2011, 09:45 В лучшем для мьютекса случае обращение через test_and_set 'быстрее' в 2 раза (в мьютексе выполнится минимум 2 test_and_set независимо от реализации, но в не-линуксах может быть и больше). В худшем случае мьютекс может быть сколь угодно медленнее. Но это большая и сложная тема, 'быстрее' тут почти бессмысленное понятие.
Название: Re: QAtomicInt vs. QMutex Отправлено: once_again_abc от Сентябрь 09, 2011, 11:02 В лучшем случае для мьютекса обращение через test_and_set 'быстрее' в 2 раза (в мьютексе выполнится минимум 2 test_and_set независимо от реализации, но в не-линуксах может быть и больше). В худшем случае мьютекс может быть сколь угодно медленнее. Но это большая и сложная тема, 'быстрее' тут быстрее почти бессмысленное понятие. есть общие практики использования того и другого? каковы критерии выбора в зависимости от ситуации? Название: Re: QAtomicInt vs. QMutex Отправлено: brankovic от Сентябрь 09, 2011, 11:14 Правило номер 1: никогда не используйте атомарные операции
Правило номер 2: никогда не используйте атомарные операции Правило номер 3: в реальном проекте за использование атомарных операций отрубают руки по локоть Если серьёзно, то пару раз видел очень эффективное использования кода на атомиках, но 1. код не простой, 2. убедить коллег что имеет смысл с этим связываться ещё сложнее. Короче использовать надо только если вы точно знаете, что это что-то даст, например если треды много времени ждут в локах. Кстати, ваш другой давешний вопрос про QSettings тоже можно решить атомиками, но решение с read-write локерами всё же предпочтительнее из-за простоты и наглядности. Название: Re: QAtomicInt vs. QMutex Отправлено: once_again_abc от Сентябрь 09, 2011, 11:36 Правило номер 1: никогда не используйте атомарные операции Правило номер 2: никогда не используйте атомарные операции Правило номер 3: в реальном проекте за использование атомарных операций отрубают руки по локоть как-то несерьезно. чем обоснованны эти правила? Если серьёзно, то пару раз видел очень эффективное использования кода на атомиках, но 1. код не простой, 2. убедить коллег что имеет смысл с этим связываться ещё сложнее. Короче использовать надо только если вы точно знаете, что это что-то даст, например если треды много времени ждут в локах. не понял ваш "например". не могли бы пояснить, что вы здесь имели ввиду? Название: Re: QAtomicInt vs. QMutex Отправлено: brankovic от Сентябрь 09, 2011, 11:57 как-то несерьезно. чем обоснованны эти правила? правила получены опытным путём. Обычно реализация даже простого алгоритма (например обычный стек) на атомиках занимает много времени и тянет за собой шлейф трудно исправимых багов. Сравнение atomic vs. locks сводится к следующему: мьютексы использовать проще, атомики потенциально эффективнее. Дальше следует выяснить насколько эффективнее. Оказывается не сильно, скажем ускорение на 50% в специфических местах может дать 5 или 1% для всей программы. А сложность алгоритмов на атомарных операциях буквально в разы больше. На поддержку такого кода обычно нет ресурсов. Это с точки зрения бизнеса. Теперь с вашей личной точки зрения. Допустим вы убьёте 2 недели на ускорение программы на 1%, оно вам надо? Как правило нет. Edit: но есть конечно implicit sharing, shared_ptr и прочие полезные вещи, которые без атомиков не реализуешь. Обычно их кто-то до вас уже реализовал, нужно просто воспользоваться. например если треды много времени ждут в локах. не понял ваш "например". не могли бы пояснить, что вы здесь имели ввиду?Если в приложении есть мьютексы-боттлнеки, т.е. места где много тредов ждут один тред захвативший мьютекс или просто очень часто треды 'сталкиваются' (т.е. засыпают из-за занятости мьютекса). Находятся такие проблемы как профилированием, так и умозрительно, поскольку профилировать такое не всегда получается. Название: Re: QAtomicInt vs. QMutex Отправлено: once_again_abc от Сентябрь 09, 2011, 12:35 Название: Re: QAtomicInt vs. QMutex Отправлено: Igors от Сентябрь 09, 2011, 13:09 ..поскольку профилировать такое не всегда получается. Ну вот зачем так на самое больное место? :) как-то несерьезно. чем обоснованны эти правила? Спасибо! :) Вы немного поэкспериментируйте, и, возможно, после этого ответы Вам уже не покажутся странными/смешными. Возьмите просто вектор, заполните его и запустите 10 ниток которые только и делают что пишут в этот вектор под защитой прекрасной, удобной конструкции напр такКод И посмотрите что у Вас со скоростью - а потом, если будет желание, обсудим и atomic. А если у Вас не найдется 15 минут чтобы это проверить - ну значит и разговор несерьезный :) Название: Re: QAtomicInt vs. QMutex Отправлено: Akon от Сентябрь 09, 2011, 17:56 Есть задачи, где без атомиков очень плохо, например, подсчет ссылок, а в целом согласен с brankovic.
Название: Re: QAtomicInt vs. QMutex Отправлено: once_again_abc от Сентябрь 14, 2011, 03:06 да, кьютишные семафоры и мьютексы довольно медленная штука.
использовал QAtomicInt + QAtomicPointer для неблокирующего кольцевого буфера в консьюмер-продюсер алгоритме. Название: Re: QAtomicInt vs. QMutex Отправлено: BRE от Сентябрь 14, 2011, 07:18 да, кьютишные семафоры и мьютексы довольно медленная штука. Нет никаких "кьютишные семафоры и мьютексы"! Эти классы в Qt всего лишь врапперы над системными объектами.Название: Re: QAtomicInt vs. QMutex Отправлено: once_again_abc от Сентябрь 14, 2011, 08:08 да, кьютишные семафоры и мьютексы довольно медленная штука. Нет никаких "кьютишные семафоры и мьютексы"! Эти классы в Qt всего лишь врапперы над системными объектами.я в курсе и это вообще то очевидно. зачем об этом говорить, да еще так(!) эмоционально? =) Название: Re: QAtomicInt vs. QMutex Отправлено: BRE от Сентябрь 14, 2011, 08:58 я в курсе и это вообще то очевидно. зачем об этом говорить, да еще так(!) эмоционально? =) Потому что уже надоело читать про тормозящие кьютешные треды, мьютексы и сокеты. ;)Насчет мьютексов... если их сравнивать с атомарными операциями, то они всегда будут медленней последних, но и задачи они выполняют разные. Задачу можно постараться решить так, что бы время ожидания на объектах синхронизации было минимально и им можно было просто пренебречь. Вот для примера, если посмотреть на то, что предлагает проверить Igors в посте # 7. Время расчета значения в каждом треде соизмеримо (в этом случае даже меньше) с временем помещения этого значения в вектор. Тут и пробовать ничего не надо, и так понятно что все нитки кроме одной будут просто ждать на мьютексе и мы получим не ускорение, а заметные тормоза. Но если изменить алгоритм и каждой нитке указать диапазон вектора для заполнения, то они все сразу заработают параллельно не мешая друг другу (да и объекты синхронизации уже не понадобятся). Или каждая нитка может заполнить свой внутренний вектор порцией данных, а мотом под защитой мьютекса добавить его в общий вектор и вернутся к заполнению внутреннего. В общем нужно стараться, что бы нитки больше работали и меньше взаимодействовали. :) Название: Re: QAtomicInt vs. QMutex Отправлено: BRE от Сентябрь 14, 2011, 09:11 И да, я не противник атомарных операций, при возможности с удовольствием пользую. :)
Название: Re: QAtomicInt vs. QMutex Отправлено: Igors от Сентябрь 14, 2011, 09:52 Насчет мьютексов... если их сравнивать с атомарными операциями, то .. Мутекс блокирует нитки, атомарные операции нет, эти вещи не взаимозаменяемы. Поэтому их сравнение бессмысленно, как и название топика. Вот для примера, если посмотреть на то, что предлагает проверить Igors в посте # 7. Время расчета значения в каждом треде соизмеримо (в этом случае даже меньше) с временем помещения этого значения в вектор. Тут и пробовать ничего не надо, и так понятно что все нитки кроме одной будут просто ждать на мьютексе и мы получим не ускорение, а заметные тормоза. Вот пока "и так все ясно" (т.е. не проверено, не прочувствовано на опыте) - толку никакого :)Насколько (во сколько раз) время расчета должно быть больше, чтобы мутекс на общем контейнере работал удовлетворительно? (напр 4 нитки, требуемый КПД хотя бы 300%). Что выигрывается с QReadWriteLocker (напр соотношение 3 чтения и 1 запись)? Но я так вижу это неинтересно проверять. Куда проще что-то прочитать/услышать и поддержать разговор напр так да, кьютишные семафоры и мьютексы довольно медленная штука. :)Но если изменить алгоритм и .. Ну так это может быть очень недешево (с точки зрения написания)Возвращаясь к теме - плохо что Qt имеет только "честный" мутекс (fair mutex). Во многих случаях удается успешно проскочить с нечестным (unfair который не останавливает нитку) вместо дорогостоящей переделки алгоритма. Название: Re: QAtomicInt vs. QMutex Отправлено: BRE от Сентябрь 14, 2011, 11:46 Мутекс блокирует нитки, атомарные операции нет, эти вещи не взаимозаменяемы. Ну и что. Что это меняет, если например нужно из разных потоков инкрементировать переменную? ::)Сравнивать их самих по себе может и бессмысленно, а вот решения с их использованием сравнивать можно вполне. Название: Re: QAtomicInt vs. QMutex Отправлено: BRE от Сентябрь 14, 2011, 12:05 Но если изменить алгоритм и .. Ну так это может быть очень недешево (с точки зрения написания)Только у меня от нее остается осадочек... что она означает - лучше сделать как попало но дешево, чем подумать и сделать хорошо и дорого. Название: Re: QAtomicInt vs. QMutex Отправлено: brankovic от Сентябрь 20, 2011, 16:32 Но если изменить алгоритм и каждой нитке указать диапазон вектора для заполнения, то они все сразу заработают параллельно не мешая друг другу (да и объекты синхронизации уже не понадобятся). 1. много тредов делающих конкурирующие атомарки (т.е. в одной кэш линии), работают медленне, чем один тред делающий то же самое. Проверенно на 16-корной машине (в 2 раза где-то в моём примере было). А всё от того, что там тоже мьютексы, только на уровне шины процессора. 2. синхронизация всё равно всегда нужна, чтобы гарантировать время жизни объекта хотя бы Очень важно звучащая фраза... "недешево с точки зрения написания"... Только у меня от нее остается осадочек... что она означает - лучше сделать как попало но дешево, чем подумать и сделать хорошо и дорого. 3. определяется колличественно в деньгах. Лучше всего сразу знать насколько хорошо нужно сделать и делать ровно на столько хорошо. Тут главное: поток задач бесконечен, если на всё тратить много времени, то легко отстать от жизни. Если двигаться слишком быстро, то легко растерять доверие клиентов из-за багов. P.S.: да, ещё кьютишные мьютексы это чёрный ящик, на винде и на posix работают совершенно по-разному. На винде нативный мьютекс это объект межпроцессного взаимодействия. Аналогом pthread_mutex скорее является CRITICAL_SECTION. По-моему лучше быть настороже имея дело с обёрткой, чем свято верить в "QMutex" == "какой-то другой мьютекс". Название: Re: QAtomicInt vs. QMutex Отправлено: BRE от Сентябрь 20, 2011, 17:11 1. много тредов делающих конкурирующие атомарки (т.е. в одной кэш линии), работают медленне, чем один тред делающий то же самое. Проверенно на 16-корной машине (в 2 раза где-то в моём примере было). А всё от того, что там тоже мьютексы, только на уровне шины процессора. 2. синхронизация всё равно всегда нужна, чтобы гарантировать время жизни объекта хотя бы Я говорил о том, что скажем вектор из 1000 элементов можно заполнять несколькими потоками, выделив каждому потоку по своему диапазону. Например, поток #1 - заполняет элементы от 0 до 249, поток # 2 - 250..499 и т.д. Под заполнением подразумевается какие-то вычисления и запись результата. На нескольких ядрах это будет быстрее чем на одном и синхронизировать там нечего будет. Название: Re: QAtomicInt vs. QMutex Отправлено: BRE от Сентябрь 20, 2011, 17:21 P.S.: да, ещё кьютишные мьютексы это чёрный ящик, на винде и на posix работают совершенно по-разному. На винде нативный мьютекс это объект межпроцессного взаимодействия. Аналогом pthread_mutex скорее является CRITICAL_SECTION. По-моему лучше быть настороже имея дело с обёрткой, чем свято верить в "QMutex" == "какой-то другой мьютекс". Ну как бы верить вообще не во что не надо. :)Что требуется от QMutex? То что бы он выполнял возложенные на него задачи и делал это максимально эффективно на каждой из поддерживаемых платформ. А как он это будет делать - это его тяжелые будни. :) Название: Re: QAtomicInt vs. QMutex Отправлено: brankovic от Сентябрь 20, 2011, 18:07 Что требуется от QMutex? То что бы он выполнял возложенные на него задачи и делал это максимально эффективно на каждой из поддерживаемых платформ. А как он это будет делать - это его тяжелые будни. :) правильно, только в жизни порой оказывается, что делает "n-ская непрозрачная либа" своё дело плохо. Поэтому обсуждать кьютный мьютекс вполне логично, как обсуждать http сервер PoCo, например. Все http сервера делают в теории одно и то же, а на практике делают, но по-разному. В частности упомянутый QMutex под винду делает что-то страшное, посмотрите код. Мне кажется там баг, но возможности проверить лень. Название: Re: QAtomicInt vs. QMutex Отправлено: BRE от Сентябрь 20, 2011, 18:10 но возможности проверить лень. У меня тоже возможности проверить лень. :) /* неплохая фраза получилась :) */+ нужно будет вспоминать/читать как-там что вообще в венде делается. Название: Re: QAtomicInt vs. QMutex Отправлено: Akon от Сентябрь 20, 2011, 20:42 Тоже был удивлен, когда увидел, что QMutex не пользует эффективный CRITICAL_SECTION, а сразу лезет к ядру, что значительно дороже. Прочем, в такой реализации возможны условные переменные на мьютексе (QWaitCondition), а на CRITICAL_SECTION они не возможны. Имхо, QMutex сделан достаточно просто/универсалено, и в силу этого он не оптимален в некоторых аспектах.
Название: Re: QAtomicInt vs. QMutex Отправлено: Igors от Сентябрь 21, 2011, 11:24 Очень важно звучащая фраза... "недешево с точки зрения написания"... :) Ну за примером ходить недалеко http://www.prog.org.ru/index.php?topic=19399.msg130940#msg130940 (http://www.prog.org.ru/index.php?topic=19399.msg130940#msg130940). Попробуем применить Ваши рекомендации (которые впрочем в данном случае совпадают с моими как видно из топика)Только у меня от нее остается осадочек... что она означает - лучше сделать как попало но дешево, чем подумать и сделать хорошо и дорого. Я говорил о том, что скажем вектор из 1000 элементов можно заполнять несколькими потоками, выделив каждому потоку по своему диапазону. 1) Вектор из элементов сначала надо создать - пробежаться по директориям в данном примере. Это может быть совсем не быстро если напр для поиска выбран том. Если уж "делать хорошо", то надо начинать сканирование с корня и затем углубляться - нередко интересующий пользователя результат может быть найден быстро. Например, поток #1 - заполняет элементы от 0 до 249, поток # 2 - 250..499 и т.д. Под заполнением подразумевается какие-то вычисления и запись результата. На нескольких ядрах это будет быстрее чем на одном и синхронизировать там нечего будет. 2) Есть такое словечко "гранулярность" - все хорошо если все задачи/кластеры выполняются за примерно одинаковое время, и наоборот. Попадется напр системный файл swap (да хотя бы просто большой sbr файл на Вындоуз) - и "быстрее" сведется к нулю. Конечно эти (и другие) проблемы можно решить - но ценой дальнейшего усложнения. Заметим что если мы бы могли безболезненно делать put/get в общий контейнер - все было бы куда проще. Ну как бы верить вообще не во что не надо. :) "Вообще говоря" этот подход хорош - невозможно (да и не нужно) вникать во все детали реализации. Но есть исключения, и они бывают часто. Прямолинейно используя "честный мутекс" можно оказаться в неудобном положении :)Что требуется от QMutex? То что бы он выполнял возложенные на него задачи и делал это максимально эффективно на каждой из поддерживаемых платформ. А как он это будет делать - это его тяжелые будни. :) Название: Re: QAtomicInt vs. QMutex Отправлено: BRE от Сентябрь 21, 2011, 11:33 Прямолинейно используя "честный мутекс" можно оказаться в неудобном положении :) Так никто не заставляет его использовать всегда и прямолинейно.QMutex в Qt сделан так, что бы на всех поддерживаемых платформах работать одинаково. Почему на венде он сделан именно так, мне кажется правильно ответил Akon: Цитировать в такой реализации возможны условные переменные на мьютексе (QWaitCondition), а на CRITICAL_SECTION они не возможны. Но если для какого-то алгоритма лучше подойдут критические секции, то можно (и нужно) сделать: Код
Название: Re: QAtomicInt vs. QMutex Отправлено: Igors от Сентябрь 21, 2011, 11:34 1. много тредов делающих конкурирующие атомарки (т.е. в одной кэш линии), работают медленне, чем один тред делающий то же самое. Проверенно на 16-корной машине (в 2 раза где-то в моём примере было). А всё от того, что там тоже мьютексы, только на уровне шины процессора. Не знаю что такое "атоиарка" (иномарка или ГАЗ ? :)) но я был весьма удивлен обнаружив что атомарный лок также тормозит (и может быть неприемлем) если конкуренция достаточно велика. |