Допустим, у меня есть 4-ядерный процессор, и я хочу запустить какой-то процесс за минимальное количество времени. Этот процесс идеально распараллеливается, поэтому я могу запускать его в бесконечном количестве потоков, и каждый поток занимает одинаковое количество времени.
Поскольку у меня 4 ядра, я не ожидаю ускорения, запустив больше потоков, чем ядер, поскольку одно ядро способно запустить только один поток в данный момент. Я не очень разбираюсь в оборудовании, так что это только предположение.
Есть ли преимущество запуска параллельного процесса на большем количестве потоков, чем на ядрах? Другими словами, завершится ли мой процесс быстрее, медленнее или примерно через столько же времени, если я запустю его с использованием 4000 потоков, а не 4 потоков?
источник
Я согласен с ответом @ Gonzalo. У меня есть процесс, который не выполняет ввод-вывод, и вот что я нашел:
Обратите внимание, что все потоки работают с одним массивом, но с разными диапазонами (два потока не обращаются к одному и тому же индексу), поэтому результаты могут отличаться, если они работают с разными массивами.
Машина 1.86 - это MacBook Air с твердотельным накопителем. Другой Mac - это iMac с обычным жестким диском (думаю, это 7200 об / мин). Машина Windows также имеет жесткий диск 7200 об / мин.
В этом тесте оптимальное количество было равно количеству ядер в машине.
источник
Я знаю, что этот вопрос довольно старый, но ситуация изменилась с 2009 года.
Теперь нужно учитывать две вещи: количество ядер и количество потоков, которые могут работать в каждом ядре.
В процессорах Intel количество потоков определяется гиперпоточностью, равной всего 2 (если доступно). Но Hyperthreading сокращает ваше время выполнения в два раза, даже если не используется 2 потока! (то есть 1 конвейер, совместно используемый двумя процессами - это хорошо, когда у вас больше процессов, но не так хорошо в противном случае. Чем больше ядер, тем лучше!)
На других процессорах у вас может быть 2, 4 или даже 8 потоков. Таким образом, если у вас есть 8 ядер, каждое из которых поддерживает 8 потоков, вы можете параллельно запустить 64 процесса без переключения контекста.
«Без переключения контекста», очевидно, не соответствует действительности, если вы работаете со стандартной операционной системой, которая будет выполнять переключение контекста для всех видов вещей вне вашего контроля. Но это главная идея. Некоторые операционные системы позволяют вам распределять процессоры так, чтобы только ваше приложение имело доступ / использование указанного процессора!
Исходя из моего собственного опыта, если у вас много операций ввода-вывода, несколько потоков это хорошо. Если у вас очень тяжелая работа с памятью (чтение источника 1, чтение источника 2, быстрые вычисления, запись), то наличие большего количества потоков не поможет. Опять же, это зависит от того, сколько данных вы читаете / пишете одновременно (т.е. если вы используете SSE 4.2 и читаете 256-битные значения, это останавливает все потоки на их шаге ... другими словами, 1 поток, вероятно, намного проще реализовать и вероятно, почти так же быстро, если не на самом деле быстрее. Это будет зависеть от вашей архитектуры процессов и памяти, некоторые продвинутые серверы управляют отдельными диапазонами памяти для отдельных ядер, поэтому отдельные потоки будут работать быстрее при условии, что ваши данные правильно хранятся ... вот почему, на некоторых архитектуры, 4 процесса будут выполняться быстрее, чем 1 процесс с 4 потоками.)
источник
Фактическая производительность будет зависеть от того, сколько добровольных выходов будет делать каждый поток. Например, если потоки вообще не выполняют операции ввода-вывода и не используют системные службы (т. Е. Они на 100% связаны с процессором), то оптимальным является 1 поток на ядро. Если потоки делают что-то, что требует ожидания, вам придется экспериментировать, чтобы определить оптимальное количество потоков. 4000 потоков могут повлечь за собой значительные затраты на планирование, так что это, вероятно, также не оптимально.
источник
Ответ зависит от сложности алгоритмов, используемых в программе. Я разработал метод вычисления оптимального количества потоков, выполнив два измерения времени обработки Tn и Tm для двух произвольных чисел потоков: n и m. Для линейных алгоритмов оптимальным числом потоков будет N = sqrt ((m n (Tm * (n-1) - Tn * (m-1))) / (n Tn-m Tm)).
Пожалуйста, прочитайте мою статью относительно расчета оптимального числа для различных алгоритмов: pavelkazenin.wordpress.com
источник
Я думал, что добавлю еще одну перспективу здесь. Ответ зависит от того, предполагает ли вопрос слабое или сильное масштабирование.
Из Википедии :
Слабое масштабирование: как время решения зависит от количества процессоров для фиксированного размера проблемы на процессор.
Сильное масштабирование: как время решения зависит от количества процессоров для фиксированного общего размера проблемы.
Если вопрос предполагает слабое масштабирование, то ответа @ Gonzalo достаточно. Однако, если вопрос предполагает сильное масштабирование, есть что добавить. При строгом масштабировании вы предполагаете фиксированный размер рабочей нагрузки, поэтому, если вы увеличите количество потоков, размер данных, с которыми должен работать каждый поток, уменьшается. На современных процессорах доступ к памяти дорогостоящий и предпочтительнее поддерживать локальность, сохраняя данные в кэш-памяти. Следовательно, вероятное оптимальное количество потоков может быть найдено, когда набор данных каждого потока помещается в кэш каждого ядра. (я не буду вдаваться в детали обсуждения того, является ли это кэш-памятью L1 / L2 / L3 системы).
Это справедливо даже в том случае, если количество потоков превышает количество ядер. Например, предположим, что в программе есть 8 произвольных единиц (или AU) работы, которая будет выполняться на 4-ядерном компьютере.
Случай 1: запустить с четырьмя потоками, где каждый поток должен завершить 2AU. Каждый поток занимает 10 секунд ( с большим количеством кешей ). С четырьмя ядрами общее время составит 10 с (10 с * 4 потока / 4 ядра).
Случай 2: запустить с восемью потоками, где каждый поток должен завершить 1AU. Каждый поток занимает всего 2 с (вместо 5 с из-за уменьшенного количества кешей ). С четырьмя ядрами общее время составит 4 с (2 с * 8 потоков / 4 ядра).
Я упростил проблему и проигнорировал накладные расходы, упомянутые в других ответах (например, переключатели контекста), но надеюсь, вы поймете, что было бы полезно иметь большее количество потоков, чем доступное количество ядер, в зависимости от размера данных, который вы ' имеем дело с.
источник
4000 потоков за один раз довольно высоки.
Ответ и да и нет. Если вы делаете много блокирующих операций ввода-вывода в каждом потоке, то да, вы можете продемонстрировать значительное ускорение, которое может составить до 3 или 4 потоков на логическое ядро.
Однако, если вы не делаете много блокировок, то дополнительные издержки с многопоточностью просто замедляют работу. Поэтому используйте профилировщик и посмотрите, где находятся узкие места в каждой, возможно, параллельной части. Если вы делаете тяжелые вычисления, то более 1 потока на процессор не поможет. Если вы делаете много передачи памяти, это тоже не поможет. Если вы делаете много операций ввода-вывода, например, для доступа к диску или доступа в Интернет, то да, несколько потоков помогут в определенной степени или, по крайней мере, сделают приложение более отзывчивым.
источник
Benchmark.
Я бы начал увеличивать количество потоков для приложения, начиная с 1, а затем перейти к примерно 100, выполнить три-пять испытаний для каждого числа потоков и построить график зависимости скорости работы от количества потоков. ,
Следует учитывать, что четырехпотоковый регистр является оптимальным, с небольшим увеличением времени выполнения после этого, но, возможно, нет. Может случиться так, что ваше приложение имеет ограниченную полосу пропускания, т. Е. Набор данных, который вы загружаете в память, огромен, вы получаете много пропусков кэша и т. Д., Так что оптимальным является 2 потока.
Вы не можете знать, пока не будете тестировать.
источник
Вы узнаете, сколько потоков вы можете запустить на своем компьютере, запустив команду htop или ps, которая возвращает число процессов на вашем компьютере.
Вы можете использовать справочную страницу о команде 'ps'.
Если вы хотите рассчитать количество всех пользователей процесса, вы можете использовать одну из следующих команд:
ps -aux| wc -l
ps -eLf | wc -l
Подсчет количества пользовательских процессов:
ps --User root | wc -l
Также вы можете использовать «htop» [Ссылка] :
Установка в Ubuntu или Debian:
Установка на Redhat или CentOS:
Если вы хотите скомпилировать htop из исходного кода, вы найдете его здесь .
источник
Идеальным является 1 поток на ядро, если ни один из потоков не заблокируется.
Один случай, когда это может быть не так: в ядре работают другие потоки, и в этом случае большее количество потоков может дать вашей программе больший отрезок времени выполнения.
источник
Одним из примеров большого количества потоков («пул потоков») против одного на ядро является пример реализации веб-сервера в Linux или в Windows.
Поскольку в Linux опрашиваются сокеты, многие потоки могут увеличить вероятность того, что один из них опрашивает правильный сокет в нужное время, но общая стоимость обработки будет очень высокой.
В Windows сервер будет реализован с использованием портов завершения ввода-вывода - IOCP - что сделает событие приложения управляемым: при завершении ввода-вывода ОС запускает резервный поток для его обработки. Когда обработка завершена (обычно с другой операцией ввода-вывода, как в паре запрос-ответ), поток возвращается к порту (очереди) IOCP, чтобы дождаться следующего завершения.
Если ввод / вывод не завершен, обработка не выполняется, и поток не запускается.
Действительно, Microsoft рекомендует не более одного потока на ядро в реализациях IOCP. Любой ввод / вывод может быть присоединен к механизму IOCP. МОК также могут быть размещены приложением, если это необходимо.
источник
timeout is an upper bound on the amount of time elapsed before select() returns. If both fields of the timeval structure are zero, then select() returns immediately. (This is useful for polling.) If timeout is NULL (no timeout), select() can block indefinitely.
Если говорить с точки зрения вычислений и памяти (научные вычисления), 4000 потоков сделают приложение действительно медленным. Частично проблема заключается в очень высоких затратах на переключение контекста и, скорее всего, в очень плохой локализации памяти.
Но это также зависит от вашей архитектуры. Из того, что я слышал, предполагается, что процессоры Niagara могут обрабатывать несколько потоков на одном ядре с использованием некоторой продвинутой техники конвейерной обработки. Однако у меня нет опыта работы с этими процессорами.
источник
Надеюсь, что это имеет смысл. Проверьте использование ЦП и памяти и установите пороговое значение. Если пороговое значение пересечено, не позволяйте создавать новый поток, иначе разрешите ...
источник