Подтвердить что ты не робот

Многопоточность и многопроцессорность

Я новичок в этом программировании и нуждаюсь в вашей точке зрения.

Мне нужно создать приложение, но я не могу вычислить его достаточно быстро. Я уже пробовал Intel TBB, и он прост в использовании, но я никогда не использовал другие библиотеки.

В многопроцессорном программировании я читаю об OpenMP и Boost для многопоточности, но я не знаю их плюсов и минусов.

В С++, когда многопоточное программирование выгодно по сравнению с многопроцессорным программированием и наоборот? Что лучше всего подходит для тяжелых вычислений или запускает множество задач...? Каковы их плюсы и минусы, когда мы создаем приложение, разработанное с ними? И, наконец, с какой библиотекой лучше работать?

4b9b3361

Ответ 1

Многопоточность означает именно то, что работает несколько потоков. Это можно сделать в однопроцессорной системе или в многопроцессорной системе.

В однопроцессорной системе при запуске нескольких потоков фактическое наблюдение за компьютером, выполняющим одновременно несколько операций (т.е. многозадачность), является иллюзией, поскольку то, что на самом деле происходит под капотом, заключается в том, что существует планировщик программного обеспечения, выполняющий временную привязку к одному процессору. Таким образом, в любой момент времени выполняется только одна задача, но планировщик переключается между задачами достаточно быстро, так что вы никогда не замечаете, что есть несколько процессов, потоков и т.д., Конкурирующих за один и тот же ресурс ЦП.

В многопроцессорной системе потребность в сокращении времени сокращается. Эффект сокращения времени по-прежнему существует, потому что современная ОС может иметь сто потоков, конкурирующих за два или более процессора, и, как правило, никогда не существует отношения 1 к 1 в количестве потоков с количеством доступных процессорных ядер. Поэтому в какой-то момент поток должен остановиться, а другой поток запускается на CPU, который разделяет два потока. Это снова обрабатывается планировщиком ОС. При этом, имея многопроцессорную систему, вы можете иметь две вещи одновременно, в отличие от однопроцессорной системы.

В конце концов, две парадигмы на самом деле несколько ортогональны в том смысле, что вам понадобится многопоточность, если вы хотите, чтобы две или более задачи выполнялись асинхронно, но из-за сокращения времени вам не обязательно нужен многопроцессорный системы для этого. Если вы пытаетесь запустить несколько потоков и выполняете задачу, которая сильно параллельна (т.е. Пытается решить интеграл), то да, чем больше ядер вы можете бросить на проблему, тем лучше. Вам не обязательно будет нужна связь 1-к-1 между потоками и процессорными ядрами, но в то же время вы не хотите выделять столько потоков, что в итоге вы получите массу простаивающих потоков, потому что они должны ждать планироваться на одном из доступных ядер процессора. С другой стороны, если ваши параллельные задачи требуют некоторого последовательного компонента, то есть поток будет ожидать результата из другого потока, прежде чем он сможет продолжить, тогда вы сможете запускать больше потоков с помощью какого-либо типа барьера или метода синхронизации, поэтому что потоки, которые должны быть бездействующими, не вращаются с использованием процессорного времени, и только потоки, которые необходимо запустить, конкурируют за ресурсы ЦП.

Ответ 2

Есть несколько важных моментов, которые, я считаю, следует добавить к отличному ответу от @Jason.

Во-первых, многопоточность не всегда является иллюзией даже на одном процессоре - есть операции, которые не связаны с процессором. В основном это I/O-диск, сеть, терминал и т.д. Основная форма для такой операции - блокировка или синхронная, то есть ваша программа ждет, пока операция не будет завершена, а затем продолжается. Во время ожидания процессор переключается на другой процесс/поток.

если у вас есть что-то, что вы можете сделать за это время (например, фоновые вычисления, ожидая ввода пользователя, обслуживая другой запрос и т.д.), у вас есть в основном два варианта:

  • использовать асинхронный ввод-вывод: вы вызываете неблокирующий ввод-вывод, предоставляя ему функцию обратного вызова, говоря, что "вызывается эта функция, когда вы закончите". Вызов немедленно возвращается, и операция ввода-вывода продолжается в фоновом режиме. Вы продолжаете с другими вещами.

  • использовать многопоточность. У вас есть выделенный поток для каждого типа задач. Пока кто-то ждет блокирующий вызов ввода-вывода, другой продолжает.

Оба подхода - сложные парадигмы программирования, у каждого есть свои плюсы и минусы.

  • с асинхронным вводом-выводом логика логики программы менее очевидна и ее трудно отслеживать и отлаживать. Однако вы избегаете проблем, связанных с безопасностью потоков.
  • с потоками, задача состоит в том, чтобы написать потокобезопасные программы. Ошибки безопасности резьбы - неприятные ошибки, которые трудно воспроизвести. Чрезмерное использование блокировки может фактически привести к ухудшению, а не к повышению производительности.

(переход к многопроцессорной обработке)

Многопоточность, популярная в Windows, потому что манипуляции с процессами довольно тяжелы в Windows (создание процесса, переключение контекста и т.д.) в отличие от потоков, которые намного легче (по крайней мере, это было так, когда я работал над Win2K).

В Linux/Unix процессы гораздо более легкие. Кроме того, потоки (AFAIK) в Linux реализованы на самом деле как некие внутренние процессы, поэтому в контекстном переключении потоков и процессов нет усиления. Однако вам нужно использовать некоторую форму IPC (межпроцессные коммуникации), как разделяемую память, каналы, очередь сообщений и т.д.

В более легкой заметке обратите внимание на SQLite FAQ, в котором говорится, что "Нити злы"!:)

Ответ 3

Чтобы ответить на первый вопрос: Лучший подход - просто использовать методы многопоточности в вашем коде, пока не дойдете до такой степени, что даже это не даст вам достаточно преимуществ. Предположим, что ОС будет обрабатывать делегирование на несколько процессоров, если они доступны.

Если вы на самом деле работаете над проблемой, когда многопоточности недостаточно, даже с несколькими процессорами (или если вы работаете на ОС, которая не использует его несколько процессоров), вы можете беспокоиться о том, как получить больше энергии. Это может означать процессы нереста в сети на другие машины.

Я не использовал TBB, но я использовал IPP и нашел его эффективным и хорошо продуманным. Boost переносится.

Ответ 4

Просто хотелось упомянуть, что программирование на основе потока (http://www.jpaulmorrison.com/fbp) - это естественно мультипрограммируемый/многопроцессорный подход к разработке приложений. Он обеспечивает согласованное представление приложений с высокого уровня на низкий уровень. Реализации Java и С# используют все процессоры на вашем компьютере, но в более старой версии С++ используется только один процессор. Однако его можно было бы довольно легко расширить, чтобы использовать BOOST (или pthreads, я полагаю), используя блокировку на соединениях. Я начал конвертировать его, чтобы использовать волокна, но я не уверен, есть ли смысл продолжать этот маршрут.:-) Обратная связь будет оценена. BTW Реализации Java и С# могут даже взаимодействовать с использованием сокетов.