Собираюсь делать новый проект на C++, при этом планирую активно
применять распарраллеливание обработки данных за счёт многопоточности.
Приложение — прежде всего планируется для Windows, но если будет поддержка кроссплатформенности — то это дополнительное преимущество.
Планирую применение библиотеки классов Qt 5.6. По крайней мере для настольной версии приложения.
В связи с этои возникает вопрос:
Оптимальная (прежде всего с точки зрения производительности) реализация многопоточности:
1) При помощи функций WinAPI — вероятно, это самый производительный вариант, однако недостаток — нет кроссплатформенности;
2) Средствами Qt — QThread кроссплатформенность есть, вопрос по производительности не очевиден, доп-бонус — отсутствие сложного кода, как в п.1;
3) Средствами STL — std::thread (примерно та же картина как и во втором пункте).
Дополнительная красота третьего пункта — если будет серверное приложение, без GUI, то не нужно "притягивать за уши" доплнительные библиотеки.
Я расположил эти пункты в порядке выбора наиболее производительного (на мой взгляд) решения.
В проекте предполагается работа нескольких потоков, а также применение методов синхронизации потоков.
Актуален обмен данными между потоками.
Здравствуйте, AlexGin, Вы писали:
AG>Оптимальная (прежде всего с точки зрения производительности) реализация многопоточности: AG>1) При помощи функций WinAPI — вероятно, это самый производительный вариант, однако недостаток — нет кроссплатформенности; AG>2) Средствами Qt — QThread кроссплатформенность есть, вопрос по производительности не очевиден, доп-бонус — отсутствие сложного кода, как в п.1; AG>3) Средствами STL — std::thread (примерно та же картина как и во втором пункте).
Производительного?
Ты думаешь, Qt или stl будут делать лишнее переключение контекста? Думаешь, затраты на тред в Qt или stl больше пары-тройки уровней вложенности вызовов кода нативной платформы, т.е., в случае Windows — WinAPI?..
Я бы не парился и делал на самой удобной платформе, т.е., в твоём случае — на Qt. Всё равно на другой платформе без Qt не взлетит, значит, надо пользовать Qt на максимум.
Лучше бы над выбором примитивов синхронизации и политикой разграничения доступа к разделяемым ресурсам задумался -- вот, где больше вероятность просадить своё приложение по производительности.
Здравствуйте, Dair, Вы писали:
D>Производительного?
Ну я тут подразумеваю прежде всего производительность в работе средств синхронизации потоков.
D>Ты думаешь, Qt или stl будут делать лишнее переключение контекста? Думаешь, затраты на тред в Qt или stl больше пары-тройки уровней вложенности вызовов кода нативной платформы, т.е., в случае Windows — WinAPI?..
Думаю, что тут могут быть принципиальные различия — особенно в организации средств синхронизации потоков.
D>Я бы не парился и делал на самой удобной платформе, т.е., в твоём случае — на Qt.
+100500
D>Всё равно на другой платформе без Qt не взлетит, значит, надо пользовать Qt на максимум.
Не факт, что "без Qt не взлетит" — если делать серверную версию, то ИМХО возможно обойтись и проще.
Однако, я бы хотел все-таки выйти на применение Qt и для этого варианта.
Тем более, что применеие многопоточности для Qt окажется удобнее, чем "голый" STL.
AG>Ну я тут подразумеваю прежде всего производительность в работе средств синхронизации потоков.
Кто тебе мешает использовать какие-нибудь EnterCriticalSection в сочетании с Qt-thread'ами?
AG>Тем более, что применеие многопоточности для Qt окажется удобнее, чем "голый" STL.
Здравствуйте, b0r3d0m, Вы писали:
B>Лучше бы над выбором примитивов синхронизации и политикой разграничения доступа к разделяемым ресурсам задумался -- вот, где больше вероятность просадить своё приложение по производительности.
Все делается step by step — сначала прорабатываем алгоритмы обработки данных в однопоточном варианте;
затем — определяемся с многопоточностью — хотя бы на уровне выбора библиотек;
после этого — прорабатываем многопоточный алгоритм и его реализацию (о чем Вы и пишете выше).
AG>Все делается step by step — сначала прорабатываем алгоритмы обработки данных в однопоточном варианте; AG>затем — определяемся с многопоточностью — хотя бы на уровне выбора библиотек; AG>после этого — прорабатываем многопоточный алгоритм и его реализацию (о чем Вы и пишете выше).
Тогда берите наиболее подходящий по остальному проекту инструмент (если у вас везде Qt -- берите Qt, используете boost -- берите boost) и не парьтесь. Как только профилировщик / QA-инженер сообщит, что приложение не удовлетворяет требованиям по производительности, тогда и начинайте задумываться.
Здравствуйте, уважаемый b0r3d0m, Вы писали:
B>Кто тебе мешает использовать какие-нибудь EnterCriticalSection в сочетании с Qt-thread'ами?
Это теоретическое предположение, или есть Ваш опыт применения подобных решений?
Здравствуйте, b0r3d0m, Вы писали:
B>В boost мне, кстати, очень нравится одна встроенная деталь -- наличие interruption point'ов, которых нет ни в стандартной библиотеке C++, ни в Qt.
Спасибо, посмотрю в этом направлении!
Здравствуйте, b0r3d0m, Вы писали:
B>Тогда берите наиболее подходящий по остальному проекту инструмент (если у вас везде Qt -- берите Qt, используете boost -- берите boost) и не парьтесь. Как только профилировщик / QA-инженер сообщит, что приложение не удовлетворяет требованиям по производительности, тогда и начинайте задумываться.
Есть желание — выбрать наиболее верный путь на этапе проектирования, чтобы в будущем не "ломать все на корню", а тонко "доработать напильником".
AG>Это теоретическое предположение, или есть Ваш опыт применения подобных решений?
Был опыт совместного использования boost::thread и CriticalSection из WinAPI.
Дело в том, что boost::mutex в текущих версиях boost'а реализован на основе Event'ов, и при определённой организации многопоточности переход на критические секции может дать прирост производительности.
AG>Есть желание — выбрать наиболее верный путь на этапе проектирования, чтобы в будущем не "ломать все на корню", а тонко "доработать напильником".
Напишите свою абстрактную обёртку над потоками и используйте её в своём коде.
Здравствуйте, уважаемый b0r3d0m, Вы писали:
B>Был опыт совместного использования boost::thread и CriticalSection из WinAPI.
Это интересно!
B>Дело в том, что boost::mutex в текущих версиях boost'а реализован на основе Event'ов, и при определённой организации многопоточности переход на критические секции может дать прирост производительности.
+100500
Я подозреваю, что это же самое относится и к std::mutex!
AG>Я подозреваю, что это же самое относится и к std::mutex!
Нет, std::mutex реализован как раз на основе критических секций (по крайней мере, в Visual Studio 2013).
В любом случае, полагаться на детали реализации не стоит.
Здравствуйте, AlexGin, Вы писали:
D>>Производительного? AG>Ну я тут подразумеваю прежде всего производительность в работе средств синхронизации потоков.
Всё равно это же решается внутри ядра ОС, т.е., средствами WinAPI под Win.
D>>Ты думаешь, Qt или stl будут делать лишнее переключение контекста? Думаешь, затраты на тред в Qt или stl больше пары-тройки уровней вложенности вызовов кода нативной платформы, т.е., в случае Windows — WinAPI?.. AG>Думаю, что тут могут быть принципиальные различия — особенно в организации средств синхронизации потоков.
Qt и stl просто врапят для тебя WinAPIшные функции. Да, накладные расходы, наверно, есть, но, если ты не синхронизируешь тысячу потоков каждый такт, проблем быть не должно.
D>>Я бы не парился и делал на самой удобной платформе, т.е., в твоём случае — на Qt. AG>+100500
D>>Всё равно на другой платформе без Qt не взлетит, значит, надо пользовать Qt на максимум. AG>Не факт, что "без Qt не взлетит" — если делать серверную версию, то ИМХО возможно обойтись и проще.
Тогда stl. Или boost вообще, там это решено уже давно, вроде как.
Но я не boost не знаю совсем, но многие хвалят.
AG>Однако, я бы хотел все-таки выйти на применение Qt и для этого варианта. AG>Тем более, что применеие многопоточности для Qt окажется удобнее, чем "голый" STL.
Если ты не пишешь супер-highload, то Qt должен нормально справиться, равно как и stl.
Здравствуйте, Dair, Вы писали:
D>Здравствуйте, AlexGin, Вы писали:
D>>>Производительного? AG>>Ну я тут подразумеваю прежде всего производительность в работе средств синхронизации потоков.
D>Всё равно это же решается внутри ядра ОС, т.е., средствами WinAPI под Win.
Да, просто это может делаться разыими способами (так, например, синхронизировать потоки можно по-разному: мьютексом или крит/секцией).
D>>>Ты думаешь, Qt или stl будут делать лишнее переключение контекста? Думаешь, затраты на тред в Qt или stl больше пары-тройки уровней вложенности вызовов кода нативной платформы, т.е., в случае Windows — WinAPI?.. AG>>Думаю, что тут могут быть принципиальные различия — особенно в организации средств синхронизации потоков.
D>Qt и stl просто врапят для тебя WinAPIшные функции.
Это естественно так. D>Да, накладные расходы, наверно, есть, но, если ты не синхронизируешь тысячу потоков каждый такт, проблем быть не должно.
Тут могут быть принципиально различные решения одних и тех же задач синхронизации (и те и другие в конечном итоге вызовут ф-ции WinAPI).
D>>>Я бы не парился и делал на самой удобной платформе, т.е., в твоём случае — на Qt. AG>>+100500
D>>>Всё равно на другой платформе без Qt не взлетит, значит, надо пользовать Qt на максимум. AG>>Не факт, что "без Qt не взлетит" — если делать серверную версию, то ИМХО возможно обойтись и проще. D>Тогда stl. Или boost вообще, там это решено уже давно, вроде как. D>Но я не boost не знаю совсем, но многие хвалят.
Да, boost хорошая штука — думаю в этом направлении.
AG>>Однако, я бы хотел все-таки выйти на применение Qt и для этого варианта. AG>>Тем более, что применеие многопоточности для Qt окажется удобнее, чем "голый" STL. D>Если ты не пишешь супер-highload, то Qt должен нормально справиться, равно как и stl.
Спасибо, уважаемый Dair!
В общем — пока раздумываю.
Мои мысли о выборе — между boost и Qt.
Здравствуйте, AlexGin, Вы писали:
AG>Доброе время суток, уважаемые коллеги!
AG>Собираюсь делать новый проект на C++, при этом планирую активно AG>применять распарраллеливание обработки данных за счёт многопоточности.
... AG>Огромное спасибо, за любые мысли!
Здравствуйте, AlexGin, Вы писали:
AG>Доброе время суток, уважаемые коллеги!
AG>Собираюсь делать новый проект на C++, при этом планирую активно AG>применять распарраллеливание обработки данных за счёт многопоточности.
AG>Приложение — прежде всего планируется для Windows, но если будет поддержка кроссплатформенности — то это дополнительное преимущество. AG>Планирую применение библиотеки классов Qt 5.6. По крайней мере для настольной версии приложения.
AG>В связи с этои возникает вопрос: AG>Оптимальная (прежде всего с точки зрения производительности) реализация многопоточности: AG>1) При помощи функций WinAPI — вероятно, это самый производительный вариант, однако недостаток — нет кроссплатформенности; AG>2) Средствами Qt — QThread кроссплатформенность есть, вопрос по производительности не очевиден, доп-бонус — отсутствие сложного кода, как в п.1; AG>3) Средствами STL — std::thread (примерно та же картина как и во втором пункте). AG>Дополнительная красота третьего пункта — если будет серверное приложение, без GUI, то не нужно "притягивать за уши" доплнительные библиотеки.
AG>Я расположил эти пункты в порядке выбора наиболее производительного (на мой взгляд) решения. AG>В проекте предполагается работа нескольких потоков, а также применение методов синхронизации потоков. AG>Актуален обмен данными между потоками.
AG>Какие могут быть соображения по выбору?
AG>Огромное спасибо, за любые мысли!
Qt/stl/boost являются очень тонким обертками над API. Оверхед по производительности минимален.
Выбор между ними имеет смысл делать только в контексте будущего перенесения кода на другие платформы, другие компиляторы (в т.ч. устаревшие), выненесения библиотеки в другие приложения (не GUI) и т.д.
Для полноты картины (особенно для выч. математики) стоит рассмотреть:
OpenMP
TBB
Распараллеливание на уровне библиотек, решающих отдельные подзадачи. (Например, решение системы линейных уравнений.)
Причем это скорее именно "другие подходы", и если переписать приложение с QThread на std::thred довольно просто, то перейти с std::thred на OpenMP (или с него) почти невозможно. Но зато многие задаче в этом подходе решаются действительно на порядок проще.
Здравствуйте, AlexGin, Вы писали:
AG>Собираюсь делать новый проект на C++, при этом планирую активно AG>применять распарраллеливание обработки данных за счёт многопоточности.
AG>Какие могут быть соображения по выбору?
В данном случае выбор не важен. Важны алгоритмы. Если параллельный алгоритм часто ждет на мьютексе, то реализация мьютекса не очень важна, на самом то деле. Он будет медленно работать. Поэтому я бы задумался прежде всего об алгоритмах и о том как избежать синхронизации, насколько это возможно. Конкретный инструмент я бы выбирал в зависимости от задачи, если у вас data-parallel алгоритмы, то стоит использовать OpenMP, например, а не явную синхронизацию, ну а если это серверное приложение — то стоит использовать то что предоставляет ваш тулкит для построения серверов (strands в boost.asio например).
CK>Если параллельный алгоритм часто ждет на мьютексе, то реализация мьютекса не очень важна, на самом то деле
Зависит от задачи. Если время, которое будет затрачено на разделяемую задачу, сравнительно небольшое, то обращаться каждый раз к ядру, например, может быть слишком расточительно.
Здравствуйте, AlexGin, Вы писали:
AG>Собираюсь делать новый проект на C++, при этом планирую активно AG>применять распарраллеливание обработки данных за счёт многопоточности.
Многопоточность -- это инструмент, который используется в двух сильно разных направлениях:
1. Parallel computing. Т.е. использование распараллеливания вычислений на все доступные ядра для уменьшения общего времени решения задачи. При этом, вероятно, каждое ядро будет выполнять одну и ту же последовательность операций, но над разными порциями данных. В задачах подобного рода используются свои наборы инструментов. Например, MPI (совокупность однопоточных процессов, возможно, работающих на разных узлах), OpenMP (как расширения языка программирования и соответствующая поддержка со стороны компилятора), Threading Building Blocks, HPX и т.п.
2. Concurrent computing. Т.е. использование всех доступных ядер для параллельного выполнения различных (почти) независимых задач. При этом, вероятно, каждая задача будет выполнять свой собственный набор операций. Тут используется несколько другой набор инструментов (хотя тот же Threading Building Blocks может пригодиться и здесь).
Соответственно, для того, чтобы давать советы, нужно понимать, что именно вы понимаете под "распараллеливанием обработки данных". Может статься (причем это наверняка так), что для ваших задач уже давным давно придуманы инструменты, которыми нужно просто суметь воспользоваться. А не пытаться повторить их на коленке с помощью WinAPI или низкоуровневых оберток над системным API (вроде std::mutex-а).
Здравствуйте, b0r3d0m, Вы писали:
B>Зависит от задачи. Если время, которое будет затрачено на разделяемую задачу, сравнительно небольшое, то обращаться каждый раз к ядру, например, может быть слишком расточительно.
Нет, не зависит от задачи. Можно захватывать мьютекс относительно редко и ненадолго, но при этом система будет медленной (из-за cache line ping-pong-а и false sharing-а), а можно захватывать мютексы очень часто, на каждый чих вообще, но система будет работать быстро. Это вопрос дизайна алгоритмов и все. Никакая навороченная реализация примитивов синхронизации не спасет от их тупого использования.
CK>а можно захватывать мютексы очень часто, на каждый чих вообще, но система будет работать быстро
Если система будет на каждый чих обращаться к ядру и засыпать в ожидании пробуждения, то о каком быстродействии может идти речь?
Здравствуйте, b0r3d0m, Вы писали:
B>Если система будет на каждый чих обращаться к ядру и засыпать в ожидании пробуждения, то о каком быстродействии может идти речь?
А мьютексы на каждый чих обращаются к ядру? Если захватывается свободный мьютекс, никакого обращения к ядру не происходит. Системный вызов выполняется только тогда, когда поток нужно усыпить, ну а задача параллельного алгоритма — сделать так, чтобы поток практически никогда не нужно было усыплять.
Пример — у тебя есть некий реестр объектов и есть потоки, которые работают с объектами из этого реестра. Обычно каждый поток работает со своим уникальным набором объектов, поэтому ты создаешь по одному локальному реестру объектов на каждый поток. Когда поток хочет начать работать с неким объектом, он берет и переносит атомарно объект из глобального реестра в свой локальный, по прошествии таймаута объект возвращается обратно, ну то есть это по сути реализация lease схемы, много где такое используется.
У глобального реестра есть мьютекс, у локального реестра есть мьютекс, у самого объекта тоже может быть мьютекс. Если потоку нужно обратиться к объекту, который был уже захвачен другим потоком — он получает адрес локального реестра того потока, захватывает его мьютекс и обращается к объекту. Но fast path — это захват одного или двух uncontended мьютексов, локальных для потока, никаких обращений к ядру, никаких дорогих операций. Дорогие операции появляются в slow path — захват мьютекса, принадлежащего другому потоку, который использовался другим потоком и даже может быть в данный момент захвачен этим другим потоком. Но это редкая операция.
Вот такие алгоритмы я имел ввиду. Это многопоточное программирвоание, все что не учитывает разницу между contended и uncontended состояниями мьютексов и памяти — многопоточным программированием не является, это просто разнообразные thread-safe реализации, которые могут иногда даже работать быстрее на многоядерных и многопроцессорных машинах (а могут и медленнее. Рассуждения о синхронизации без вот этого вот контекста — просто пустая трата времени, которая показывает только то, что рассуждающий очень поверхностно понимает многопоточность.
Здравствуйте, b0r3d0m, Вы писали:
CK>>А мьютексы на каждый чих обращаются к ядру? B>Насколько я знаю, в Windows -- да.
Win API функции тоже могут делать что-нибудь в user-space. Я не знаю как это точно реализовано в win-api (не писал ничего под эту платформу лет эдак шесть), но например в linux никто никогда не делает системные вызовы напрямую — все вызовы завернуты в вызовы glibc и тот же pthread_mutex_lock много чего делает в userspace прежде чем делать системный вызов, там в принципе может и без системного вызова обойтись. Подозреваю в win32 api что-то похожее, ну либо у них там мьютекс это действительно голый объект ядра, а поддержку в userspace имеют только критические секции.
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, AlexGin, Вы писали:
AG>>Собираюсь делать новый проект на C++, при этом планирую активно AG>>применять распарраллеливание обработки данных за счёт многопоточности.
S>Многопоточность -- это инструмент, который используется в двух сильно разных направлениях:
S>1. Parallel computing. Т.е. использование распараллеливания вычислений на все доступные ядра для уменьшения общего времени решения задачи. При этом, вероятно, каждое ядро будет выполнять одну и ту же последовательность операций, но над разными порциями данных. В задачах подобного рода используются свои наборы инструментов. Например, MPI (совокупность однопоточных процессов, возможно, работающих на разных узлах), OpenMP (как расширения языка программирования и соответствующая поддержка со стороны компилятора), Threading Building Blocks, HPX и т.п.
Да — именно об этом и идет речь в моём посте.
S>2. Concurrent computing. Т.е. использование всех доступных ядер для параллельного выполнения различных (почти) независимых задач. При этом, вероятно, каждая задача будет выполнять свой собственный набор операций. Тут используется несколько другой набор инструментов (хотя тот же Threading Building Blocks может пригодиться и здесь).
Это не для данного случая.
S>Соответственно, для того, чтобы давать советы, нужно понимать, что именно вы понимаете под "распараллеливанием обработки данных". Может статься (причем это наверняка так), что для ваших задач уже давным давно придуманы инструменты, которыми нужно просто суметь воспользоваться.
Вполне возможно.
S>А не пытаться повторить их на коленке с помощью WinAPI или низкоуровневых оберток над системным API (вроде std::mutex-а).
Дело в том, что в предшествующих разработках у меня наблюдалась работа над "вариантом 2".
Здравствуйте, b0r3d0m, Вы писали:
CK>>ну либо у них там мьютекс это действительно голый объект ядра, а поддержку в userspace имеют только критические секции. B>Да.
B>Помимо этого, в Windows они могут шариться между процессами.
The threads of a single process can use a critical section object for mutual-exclusion synchronization. The process is responsible for allocating the memory used by a critical section object, which it can do by declaring a variable of typeCRITICAL_SECTION. Before using a critical section, some thread of the process must call InitializeCriticalSection orInitializeCriticalSectionAndSpinCount to initialize the object.
Здравствуйте, AlexGin, Вы писали:
S>>Соответственно, для того, чтобы давать советы, нужно понимать, что именно вы понимаете под "распараллеливанием обработки данных". Может статься (причем это наверняка так), что для ваших задач уже давным давно придуманы инструменты, которыми нужно просто суметь воспользоваться. AG>Вполне возможно.
Ну так приоткройте тайну, может вам более конкретные вещи посоветуют.
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, AlexGin, Вы писали:
S>>>Соответственно, для того, чтобы давать советы, нужно понимать, что именно вы понимаете под "распараллеливанием обработки данных". Может статься (причем это наверняка так), что для ваших задач уже давным давно придуманы инструменты, которыми нужно просто суметь воспользоваться. AG>>Вполне возможно.
S>Ну так приоткройте тайну, может вам более конкретные вещи посоветуют.
Обработка данных. Эта обработка должна быть распараллелена по всем ядрам CPU.
Как подсчитать количество ядер — дело ясное:
Ну а дальше — создать столько потоков (threads), сколько у нас ядер — и считать.
Все потоки считают по одинаковому алгоритму, складывают данные (результаты) в общие коллекции.
Вот собственно и все премудрости.
AG>Нет — критические секции в WinAPI не разделяются между процессами
Я про Mutex'ы.
AG>Именно поэтому у меня и возник данный вопрос: AG>можно ли в Qt, boost, STL использовать такие штуковины, как критические секции
Да что вы так WinAPI боитесь-то? Напишите свой враппер, протестируйте его и забудьте про детали реализации.
Алсо, у Microsoft есть заголовочный файл concrt.h, в котором, помимо всего прочего, есть обёртка над критическими секциями. Насколько он публичный, я не в курсе, надо гуглить.
Здравствуйте, AlexGin, Вы писали:
AG>В связи с этои возникает вопрос: AG>Оптимальная (прежде всего с точки зрения производительности) реализация многопоточности: AG>1) При помощи функций WinAPI — вероятно, это самый производительный вариант, однако недостаток — нет кроссплатформенности; AG>2) Средствами Qt — QThread кроссплатформенность есть, вопрос по производительности не очевиден, доп-бонус — отсутствие сложного кода, как в п.1; AG>3) Средствами STL — std::thread (примерно та же картина как и во втором пункте). AG>Дополнительная красота третьего пункта — если будет серверное приложение, без GUI, то не нужно "притягивать за уши" доплнительные библиотеки.
AG>Какие могут быть соображения по выбору?
int QThread::idealThreadCount () [static]
Возвращает идеальное количество потоков, которое может быть запущено в системе. Она делает запрос количества процессорных ядер, как реальных, так и логических. Эта функция возвращает -1, если количество процессорных ядер не может быть определено.
Ещё добавлю, что параллельное программирование в Qt состоит не из одного QThread.
Пространство имен QtConcurrent предоставляет высокоуровневые API, которые делают возможным написание многопоточных программ без использования низкоуровневых потоковых примитивов, таких как мьютексы, блокировки чтение-запись, условия ожидания или семафоры. Программы, написанные с помощью QtConcurrent, автоматически приводят количество используемых потоков в соответствие с доступным количеством процессорных ядер. Это означает, что приложения, написанные сегодня, будут продолжать масштабироваться при развертывании на многоядерных системах в будущем.
SISD (Single Instruction, Single Data) – системы, в которых существует одиночный поток команд и одиночный поток данных. К такому типу можно отнести обычные последовательные ЭВМ;
SIMD (Single Instruction, Multiple Data) – системы c одиночным потоком команд и множественным потоком данных. Подобный класс составляют многопроцессорные вычислительные системы, в которых в каждый момент времени может выполняться одна и та же команда для обработки нескольких информационных элементов; такой архитектурой обладают, например, многопроцессорные системы с единым устройством управления. Этот подход широко использовался в предшествующие годы (системы ILLIAC IV или CM-1 компании Thinking Machines), в последнее время его применение ограничено, в основном, созданием специализированных систем;
MISD (Multiple Instruction, Single Data) – системы, в которых существует множественный поток команд и одиночный поток данных. Относительно этого типа систем нет единого мнения: ряд специалистов считает, что примеров конкретных ЭВМ, соответствующих данному типу вычислительных систем, не существует и введение подобного класса предпринимается для полноты классификации; другие же относят к данному типу, например, систолические вычислительные системы (см. [51, 52]) или системы с конвейерной обработкой данных;
MIMD (Multiple Instruction, Multiple Data) – системы c множественным потоком команд и множественным потоком данных. К подобному классу относится большинство параллельных многопроцессорных вычислительных систем.
Причём за использование того же OpenMP, MPI или ещё чего-нибудь придётся заплатить свою цену. Если нужно обычное прикладное приложение, то проще использовать чистый Qt. Могу сказать и по другому, если используется Qt, то это явно прикладное приложение, а не какой-нибудь навороченный кластер на тысячи компьютеров, иначе это был бы boost или что-то в этом роде.
Здравствуйте, b0r3d0m, Вы писали:
_>>Хочешь рапараленлить вычисления MPI, OpenACC, OpenCL
B>Тогда уж и про OpenMP не забываем.
Дык OpenMPI реализация MPI также как и MPICH
Здравствуйте, AlexGin, Вы писали:
AG>Актуален обмен данными между потоками.
Нужно сделать так чтобы был не актуален. AG>Какие могут быть соображения по выбору?
QT AG>Огромное спасибо, за любые мысли!
Только QT.
Здравствуйте, b0r3d0m, Вы писали:
CK>>А мьютексы на каждый чих обращаются к ядру? B>Насколько я знаю, в Windows -- да.
Емнип, кажется у Рихтера давно читал, что при захвате CRITICAL_SECTION делается короткий спинлок чтобы сразу не уходить в ядро.
Вообще в Windows Vista кроме Aero темы появилось новое ядро с новыми примитивами: CONDITION_VARIABLE и SRWLOCK. Последний можно использовать в реализации std::mutex, но не знаю так ли это в Visual C++
Здравствуйте, b0r3d0m, Вы писали:
AG>>Нет — критические секции в WinAPI не разделяются между процессами
B>Я про Mutex'ы.
AG>>Именно поэтому у меня и возник данный вопрос: AG>>можно ли в Qt, boost, STL использовать такие штуковины, как критические секции
B>Да что вы так WinAPI боитесь-то? Напишите свой враппер, протестируйте его и забудьте про детали реализации.
Во-первых — я не боюсь WinAPI.
Более того, работал на старой работе в течение примерно 5-ти лет очень плотно и с WinAPI, и с MFC.
Посему и понимаю как достоинства, так и недостатки данного стека технологий.
Достоинство — хорошая оптимизация по производительности под ОС семейства Windows.
Дальше начинаются недоститки: нет кроссплатформенности — главный и основной из них.
Отсутствие лаконичности — "монстроидальность" недостаток небольшой, всегда можно найти класс-обёртку (на худой конец — взять что-то из MFC).
Во-вторых я прекрасно понимаю, что на сегодняшний день надо осваивать кроссплатформенные технологии.
Если завтра мой код придется портировать на Linux, то это портирование должно проходить максимально беспроблемно.
И вот тут уже "альтернативние" средства работы с многопоточностью начинают сильно проигрывть по производительности: http://stackoverflow.com/questions/9997473/stdmutex-performance-compared-to-win32-critical-section
Относительно неплохим вариантом здесь выглядит свой собственный класс-обёртка,
оптимизированный к требованиям моего конкретного проекта и "скрывающий" детали реализации механизмов многопоточности.
Таким образом, мы будем иметь два таких класса — один для WinAPI, другой — для Linux.
Оба этих класса — должны наследовать общий интерфейс (aka абстрактный базовый класс).
B>Алсо, у Microsoft есть заголовочный файл concrt.h, в котором, помимо всего прочего, есть обёртка над критическими секциями. Насколько он публичный, я не в курсе, надо гуглить.
Есть такая штука, но это достаточно "редкий зверь".
И нет уверенности, что он не привязан к специфике конкретной ОС или студии. Его применение не выглядит как верное решение.
Вместо этого, для Windows можно всю обертку сделать на чистом WinAPI.
Здравствуйте, PM, Вы писали:
PM>Вообще в Windows Vista кроме Aero темы появилось новое ядро с новыми примитивами: CONDITION_VARIABLE и SRWLOCK. Последний можно использовать в реализации std::mutex, но не знаю так ли это в Visual C++
PM>https://msdn.microsoft.com/en-us/magazine/jj721588.aspx
Я бы, честно говоря, использовал везде std::mutex и все. Ну может быть boost::mutex если нужен бустовый thread::interrupt.
CK>Я бы, честно говоря, использовал везде std::mutex и все. Ну может быть boost::mutex если нужен бустовый thread::interrupt.
Кстати, я лично натыкался на один очень неприятный баг std::mutex -- его использование в DLL ведёт к увеличению счётчика ссылок на эту самую DLL без последующего уменьшения (следовательно, хост-процесс не выгрузит её при вызове FreeLibrary, так что не будет вызвана функция DllMain и деструкторы объектов со static storage duration).
Здравствуйте, AlexGin, Вы писали:
S>>Ну так приоткройте тайну, может вам более конкретные вещи посоветуют. AG>Обработка данных. Эта обработка должна быть распараллелена по всем ядрам CPU.
AG>Ну а дальше — создать столько потоков (threads), сколько у нас ядер — и считать. AG>Все потоки считают по одинаковому алгоритму, складывают данные (результаты) в общие коллекции. AG>Вот собственно и все премудрости.
OpenMP или Intel.TBB. Это простой кейс — data-parallel алгоритм. Если делать это не через OpenMP итп то нужно подумать вот о чем:
— Какой минимальный размер входных данных, при которых нужно начинать выполнять обработку параллельно?
— На блоки какого размера разбивать входные данные (их нельзя разбить на N блоков, где N-количество цпу).
— Как балансировать нагрузку.
— Как складывать результаты (если в одну общую коллекцию, то тут нужно избежать false-sharing-а и race-ов, а также правильно организовать синхр-ю, чтобы не получить падение производительности, вместо прироста, если каждый поток будет писать в свою коллекцию (более предпочтительно), то нужно подумать о том, как объединять результаты).
В общем, это все делается элементарно, если есть parallel for или его аналог, мне кажется такое сейчас и в Qt должно быть.
Здравствуйте, b0r3d0m, Вы писали:
B>Кстати, я лично натыкался на один очень неприятный баг std::mutex -- его использование в DLL ведёт к увеличению счётчика ссылок на эту самую DLL без последующего уменьшения (следовательно, хост-процесс не выгрузит её при вызове FreeLibrary, так что не будет вызвана функция DllMain и деструкторы объектов со static storage duration).
Потому что люди, пишущие на winapi, должны страдать.
Здравствуйте, AlexGin, Вы писали:
AG>Какие могут быть соображения по выбору? AG>Огромное спасибо, за любые мысли!
Соображение очень простое. Не та проблема ставится. Она надуманная. Используй самый простой инструмент, он по скорости будет ничем не хуже. А скорость будешь потом искать, профайлером.
CK>Очень очень старая хрень, думаю что это не основное средство для разработки windows приложений уже давно
Что именно? CRITICAL_SECTION? Оно ещё как в ходу.
Здравствуйте, b0r3d0m, Вы писали:
B>Что именно? CRITICAL_SECTION? Оно ещё как в ходу.
Если серьезно — MS делает свою стандартную библиотеку с человеческими примитивами синхронизации не просто так, наверное, а из расчета, что ей будут пользоваться.
CK>Если серьезно — MS делает свою стандартную библиотеку с человеческими примитивами синхронизации не просто так, наверное, а из расчета, что ей будут пользоваться.
std::mutex-то? Я ведь уже сказал, что в нём неплохой такой баг есть, а так я и не против его использования, где я говорил обратное?
Здравствуйте, b0r3d0m, Вы писали:
B>std::mutex-то? Я ведь уже сказал, что в нём неплохой такой баг есть, а так я и не против его использования, где я говорил обратное?
Здравствуйте, b0r3d0m, Вы писали:
CK>>А ты его засабмитил куда следует? B>Он уже до меня был засабмичен.
Забавно.
The trige meeting decided to not fix this particular issue. As a workaround it's recomended to terminate all the threads that were started or wait until they are finished.
Здравствуйте, Dair, Вы писали:
D>В Linux тоже "использование в DLL .so ведёт к увеличению счётчика ссылок на эту самую DLL .so без последующего уменьшения"?
Похоже что там не сбрасывается счетчик только если есть живые потоки, запущенные из этой dll, сложно это багом назвать, честно говоря.
D>В Linux тоже "использование в DLL .so ведёт к увеличению счётчика ссылок на эту самую DLL .so без последующего уменьшения"?
Нет. Да и в случае Windows это всего лишь баг в реализации стандартной библиотеки. Если использовать соответствующие примитивы синхронизации (например, ту же CRITICAL_SECTION) напрямую, то увеличения счётчика ссылок не наблюдается.
Здравствуйте, уважаемый velkin!
Огромное спасибо за столь развёрнутый ответ!
Скорее всего и остановим выбор именно на Qt!
По крайней мере в кроссплатформенной реализации.
Возможно, стоит применять Qt многопоточность даже для Windows реализации.
Тут надо проеэкспнриментировать — посчитать производительность, как она будет в сравнении с WinAPI.
V>Но принципиальной разницы в программировании для того и другого процессора нет, просто нужно определиться с общей стратегией.
Собственно этим и занимаюсь
Здравствуйте, chaotic-kotik, Вы писали:
PM>>Вообще в Windows Vista кроме Aero темы появилось новое ядро с новыми примитивами: CONDITION_VARIABLE и SRWLOCK. Последний можно использовать в реализации std::mutex, но не знаю так ли это в Visual C++
PM>>https://msdn.microsoft.com/en-us/magazine/jj721588.aspx
CK>Я бы, честно говоря, использовал везде std::mutex и все. Ну может быть boost::mutex если нужен бустовый thread::interrupt.
Я бы тоже Просто топикстартеру зачем-то понадобился высокопроизводительный mutex и я вспомнил, что SRWLOCK работает в userspace.
Кстати, посмотрел в Visual C++ 2015 update3, там до сих пор какая-то лабуда в виде `_Mtx_internal_imp_t` внутри std::mutex. Похоже из-за того, что приходится поддерживать Windows XP.
Здравствуйте, AlexGin, Вы писали:
AG>Возможно, стоит применять Qt многопоточность даже для Windows реализации. AG>Тут надо проеэкспнриментировать — посчитать производительность, как она будет в сравнении с WinAPI.
Думаю пункт 1, то есть WinAPI существенной роли не сыграет, в особенности, если понимать на что влияют технологии многопоточного программирования Qt.
В дебиане нажимаем Ctrl+Alt+F1, вводим root или другого пользователя с паролем и запускаем программу. Потом обратно выход на рабочий стол Ctrl+Alt+F7. Фишка в том, что функционал отвечающий за работу с параллельными потоками исполнения лежит в модуле QtCore. Между прочим, если совместить кроссплатформенные библиотеки, то тоже выйдет неплохое кроссплатформенное решение. Другое дело это не всегда целесообразно, особенно, если можно обойтись средствами Qt.
. По прошествии многих лет могу сказать, что идея тоже не целесообразна, хотя всё прекрасно работает. Суть в том, что чем больше программист создаёт себе проблем, тем хуже для него. Отсюда вывод, не создавать надуманных проблем, лучше не идеально работающая система, чем идеальная не работающая.
Я не зря привёл пример компьютеров с низкой и высокой вычислительной мощью. Сдаётся мне в прикладном приложении можно убить месяцы на разработку велосипеда, а школьник Вася Пупкин стандартным функционалом на коленеке сделает так же или даже лучше, плюс ещё и кроссплатформенно. При этом он может и слов таких не знать, которыми обменивались в этой теме.
Никаких, многопоточность уже входит в стандарт, ею и нужно пользоваться.
std::thread то есть.
При этом на производительность это либо вообще не повлияет, либо если и повлияет, то очень незначительно.
Здравствуйте, chaotic-kotik, Вы писали:
CK>Win API функции тоже могут делать что-нибудь в user-space. Я не знаю как это точно реализовано в win-api (не писал ничего под эту платформу лет эдак шесть), но например в linux никто никогда не делает системные вызовы напрямую — все вызовы завернуты в вызовы glibc и тот же pthread_mutex_lock много чего делает в userspace прежде чем делать системный вызов, там в принципе может и без системного вызова обойтись. Подозреваю в win32 api что-то похожее, ну либо у них там мьютекс это действительно голый объект ядра, а поддержку в userspace имеют только критические секции.
В венде есть функция CreateMutex, она возвращает HANDLE (аналог, в некотором смысле, юниксного file descriptor) и именно этот объект виндовые программисты привыкли называть мьютексом. Любое телодвижение с ним — это системный вызов.
Есть так же объект по имени CRITICAL_SECTION, по смыслу своему он мьютекс-мьютексом, а все операции с ним, насколько возможно, делаются в user space (аналогично быстрым посиксным мьютексам в линухе). Его виндовые программисты привыкли называть не мьютексом, а критической секцией.
Такая вот культурно-терминологическая особенность.
QThread::idealThreadCount()
AG>Ну а дальше — создать столько потоков (threads), сколько у нас ядер — и считать. AG>Все потоки считают по одинаковому алгоритму, складывают данные (результаты) в общие коллекции. AG>Вот собственно и все премудрости.
Соглашусь с тем, что вы зря городите зоопарк технологий. Если уж проект на Qt — то используйте Qt. Искать узкие места и альтернативы начнёте когда упрётесь по производительности в реальных условиях.
Здравствуйте, AlexGin, Вы писали:
AG>Доброе время суток, уважаемые коллеги!
AG>Собираюсь делать новый проект на C++, при этом планирую активно AG>применять распарраллеливание обработки данных за счёт многопоточности.
Как правильно заметили ранее "Преждевременная оптимизация есть корень всех зол".
По опыту скажу выбор Qt оптимален для проектирования кросплатформенного именно ГУИ приложения, он очень своеобразен и сложен, при работе с ним 60% времени уходит на чтения их документации, 30% на гугление и возгласы "сука-идиоты нельзя было написать это сразу", и Только 10% на собственно работу над проектом.
ВинАпи понятен как дважды два и всё отскакивает от зубов, ну для вашего случая порекомендовал бы чистый std либ.
Когда[если] захотите распаралелится там для этого всё есть.
Икс>По опыту скажу выбор Qt оптимален для проектирования кросплатформенного именно ГУИ приложения,
Делал сервера на Qt. Может, конечно, показаться извратом, но очень сильно упрощает процесс. Из коробки есть интроспекция / рефлексия / базы / строки / многопоточность / кросс-поточные сигналы, COW для любых типов данных, файловая система и т.п. В общем, почти всё что надо. Ну и да, для GUI достаточно удобен.
Не нужно в результате городить зоопарк библиотек.
Икс> он очень своеобразен и сложен, при работе с ним 60% времени уходит на чтения их документации, 30% на гугление и возгласы "сука-идиоты нельзя было написать это сразу", и Только 10% на собственно работу над проектом.
Вопрос опыта. Как и с любым другим фреймворком / платформой / языком. Единственное, что мне не нравится в Qt, так это работа с json-ом. Нет возможностей для удобной генерации. Ну и да, из коробки нет http сервера.
Икс>ВинАпи понятен как дважды два и всё отскакивает от зубов, ну для вашего случая порекомендовал бы чистый std либ.
Только трудозатраты на несколько порядков выше. ВинАпи — это си, а не си плюс плюс. В лучшем случае — "си с классами".