Название: Проблемы с QMutex Отправлено: Igors от Ноябрь 04, 2009, 04:38 Здравствуйте
Приаттачен простой пример 100 строк. Запускается NUM_THREAD ниток, они делают какую-то работу и завершаются. Все работает "как доктор прописал": больше ниток - быстрее считаем (при наличии процессоров). Проблема: скорость резко падает (во несколько раз) если я вставляю в расчет блокировку QMutexLocker Все то же самое в нативном коде (без Qt). Возможно это возникает только на моей платформе, или я что-то упустил. Если несложно проверить - буду благодарен. Порядок тестирования: - запустить как есть, через несколько секунд на консоли напечатается время - поставить #define CRAZY_TEST 1 и опять запустить. У меня время намного больше. На 4 нитках трудно дождаться - если железо слабенькое можно уменьшить NUM_CALC Спасибо Название: Re: Проблемы с QMutex Отправлено: spectre71 от Ноябрь 04, 2009, 08:07 Igors, если делаешь тест, то делай компилябильный проект.
===== 1) Код
В данном случае лучше не использовать QMutexLocker ! Каждую итерацию создается и уничтожается объект QMutexLocker, что накладно! Лучше так Код
2) Код
- Опять же, каждую итерацию цикла создается и уничтожается объект QMutexLocker, что очень очень накладно (здесь твои тормоза) - Не вижу ни какого смысла в QMutexLocker test(&mutexTmp); в данном случае - И вообще, данная функция ничего не возвращает Могу предположить что это написано только ради теста. Теперь советы по оптимизации: - Не используй QMutexLocker для часто вызываемого участка кода, используй непосредственно QMutex (lock/unlock), поскольку создание и уничтожение объекта дорго. - Желательно выносить(не блокировать) участки которые этого не требуют, например: ++mNumCalc; - Во определенных случаях, если есть глобалы типа int, то для работы с ними не обязателено использовать QMutex. Можно использовать атомарные операции. Пример: Предположим что int sumVal глобально накапливает некоторую сумму по всем потокам: Код
Это гораздо дешевле чем: Код
И кстати из QAtomicInt sumVal; читать всегда безопасно. Название: Re: Проблемы с QMutex Отправлено: Igors от Ноябрь 04, 2009, 13:24 Здравствуйте, Spectre
1) Igors, если делаешь тест, то делай компилябильный проект. Что-то не так с файлом, приходится возиться чтобы откомпилить? Скажите что - исправлюсь. Разумеется, все вычисления не имеют никакого смысла - незачем здесь вмешивать большую предметную часть.2) Возникают ли у Вас тормоза и на какой платформе? Судя по Вашему ответу да, но лучше спросить :) 3) Обертка QMutexLocker ест немного, но все равно уберем для чистоты. Вообще специфика Qt здесь ни при чем, та же ситуация с родным pmutex_thread_lock 4) Использование QAtomicInt мне не подходит (см. топик "GetPixel thread-safe" в этом же разделе). 5) Мое мнение: блокировка мутексом (в Qt и OS) может быть медленной ЕСЛИ 2 или более ниток ждут. В примере ниже можно регулировать частоту блокировок макросом NUM_PORTION. Дело не столько в том что становится меньше блокировок, а в том что нитки меньше "пересекаются". Это же подтверждает тест с 1 ниткой: да, мутекс что-то съел но вполне в рамках приличий. Другие мнения? Название: Re: Проблемы с QMutex Отправлено: kuzulis от Ноябрь 04, 2009, 13:40 А если попробовать QReadWriteLock и т.п.?
Название: Re: Проблемы с QMutex Отправлено: Igors от Ноябрь 04, 2009, 14:28 А если попробовать QReadWriteLock и т.п.? Твк все "и т.п." сделано на тех же мутексах :) А также мне надо лочить не только обращения к swap файлу, но и не допускать работы с данными которые могут быть выгружены. Не вижу др. кандидата кроме мутекса Название: Re: Проблемы с QMutex Отправлено: kuzulis от Ноябрь 04, 2009, 14:32 А QSharedPointer ?
Название: Re: Проблемы с QMutex Отправлено: Igors от Ноябрь 04, 2009, 16:00 А QSharedPointer ? Открываем исходник QSharedPointer.cpp ....Хммм.... все пестрит вызовами QMutexLocker lock(&kd->mutex); :) Название: Re: Проблемы с QMutex Отправлено: SASA от Ноябрь 04, 2009, 19:57 2 Igors. Мутексы - это дорого, полюбому ;)
2 Spectre. А как работает QAtomicInt? За счёт чего достигается атомарность? Название: Re: Проблемы с QMutex Отправлено: Igors от Ноябрь 04, 2009, 20:07 2 Igors. Мутексы - это дорого, полюбому ;) Очень элегантный ответ :) Если нетрудно, укажите теоретический источник. А если есть собственный опыт (любой) - расскажите обязательноНазвание: Re: Проблемы с QMutex Отправлено: shadone от Ноябрь 04, 2009, 21:13 2 Igors. Мутексы - это дорого, полюбому ;) Очень элегантный ответ :) Если нетрудно, укажите теоретический источник. А если есть собственный опыт (любой) - расскажите обязательнов двух словах потому что требует синхронизации кэша между процессорами. http://en.wikipedia.org/wiki/Mutual_exclusion http://en.wikipedia.org/wiki/Critical_section http://en.wikipedia.org/wiki/Memory_barrier http://en.wikipedia.org/wiki/ABA_problem Название: Re: Проблемы с QMutex Отправлено: shadone от Ноябрь 04, 2009, 21:15 - Опять же, каждую итерацию цикла создается и уничтожается объект QMutexLocker, что очень очень накладно (здесь твои тормоза) все правильно. за одним дополнением - стоимостью создания/удаления объекта QMutexLocker можно пренебречь - это на порядки дешевле чем сама операция блокировки мьютекса.еще одно дополнение - чтение int без блокировки безопасная операция, если вас не пугают проблему кэширования данных. int val = 0; // global value accessible by several threads ... if (val == 0) { int foo = val; // might be non-0 } Название: Re: Проблемы с QMutex Отправлено: Igors от Ноябрь 04, 2009, 21:50 Здравствуйте, Денис
Спасибо за подборочку по теории. стоимостью создания/удаления объекта QMutexLocker можно пренебречь - это на порядки дешевле чем сама операция блокировки мьютекса. Насчет стоимость QMutexLocker полностью согласен. Насчет стоимости блокировки - не так просто/очевидно. Пример: простой цикл из 1 миллиона несложных вычислений. Вставьте в тело цикла QMutexLocker - замедления не наблюдается. еще одно дополнение - чтение int без блокировки безопасная операция, если вас не пугают проблему кэширования данных. Опасная. Дело совсем не в том что "переменная может храниться в регистре" - проблемы будут и без этогоКод: int val = 0; // global value accessible by several threads Название: Re: Проблемы с QMutex Отправлено: kuzulis от Ноябрь 05, 2009, 08:33 а это если прикрутить?
http://www.linux.org.ru/view-message.jsp?msgid=4199760&lastmod=1257363282391 :) Название: Re: Проблемы с QMutex Отправлено: spectre71 от Ноябрь 05, 2009, 10:37 2 Spectre. А как работает QAtomicInt? За счёт чего достигается атомарность? Как конкретно реализован QAtomicInt в QT не смотрел.Но по идее должны использоваться нативные вызовы конкретной операционки. Например для Windows - Interlocked функции. С другой стороны атомарные операции должны поддерживаться на уровне определенных команд процессоров. Название: Re: Проблемы с QMutex Отправлено: Igors от Ноябрь 05, 2009, 12:34 а это если прикрутить? Хмм... пригодится или нет - не знаю. Но интересно, спасибо за наводкуhttp://www.linux.org.ru/view-message.jsp?msgid=4199760&lastmod=1257363282391 :) Название: Re: Проблемы с QMutex Отправлено: Igors от Ноябрь 05, 2009, 17:39 Вот неплохая статейка о том что делает atomic
http://labs.trolltech.com/blogs/category/c/ (http://labs.trolltech.com/blogs/category/c/) Название: Re: Проблемы с QMutex Отправлено: Akon от Октябрь 01, 2010, 10:52 2 Igors. Мутексы - это дорого, полюбому Например под виндой мьютекс реализован через Event - это объект ядра, т.е. при выполнении кода блокировки/разблокировки мьютекса происходит переход в режим ядра. На платформе x86 это очень накладно (в районе тыщи машинных инструкций). В винде есть не связанный с ядром примитив синхронизации CriticalSection (значительно быстрее Event'a). Для блокировки в пределах одного процесса это самое оно. Если бы под виндой мьютекс был реализован через CriticalSection было бы значительно лучше. Зато мьютекс нельзя было бы ожидать в QWaitCondition. |