Как быстрее выполнить те же вычисления на 4-ядерном процессоре: 4 потока или 50 потоков? - PullRequest
7 голосов
/ 08 февраля 2012

Предположим, что у нас установлен фиксированный объем вычислений, без блокировки, сна, ожидания ввода-вывода. Работу можно распараллелить очень хорошо - она ​​состоит из 100 миллионов небольших и независимых расчетных задач.

Что быстрее для 4-ядерного процессора - запустить 4 потока или ... скажем, 50? Почему второй вариант должен быть slover и сколько slover?

Как я полагаю: когда вы запускаете 4 тяжелых потока на 4-ядерном процессоре без других процессорных потоков / потоков, планировщик может вообще не перемещать потоки между ядрами; в этой ситуации нет причин делать это. Core0 (основной ЦП) будет отвечать за выполнение обработчика прерываний для аппаратного таймера 250 раз в секунду (базовая конфигурация Linux) и других аппаратных обработчиков прерываний, но другие ядра могут не беспокоиться.

Сколько стоит переключение контекста? Время для сохранения и восстановления регистров процессора для другого контекста? А как насчет кешей, конвейеров и различных вещей, предсказывающих код внутри CPU? Можем ли мы сказать, что каждый раз, когда мы переключаем контекст, мы вредим кешам, конвейерам и некоторым средствам декодирования кода в CPU? Таким образом, чем больше потоков выполняется на одном ядре, тем меньше работы они могут выполнять вместе по сравнению с их последовательным выполнением?

Вопрос о кешах и другой аппаратной оптимизации в среде многопоточности - интересный вопрос для меня сейчас.

Ответы [ 5 ]

11 голосов
/ 08 февраля 2012

Как отмечает @Baile в комментариях, это сильно зависит от приложения, системы, среды.

И поэтому я не собираюсь придерживаться жесткого подхода, когда упоминается ровно 1 поток для каждого ядра. (или 2 потока / ядро ​​в случае Hyperthreading)

Как опытный программист с разделяемой памятью, из своего опыта я видел, что оптимальное число потоков (для 4-ядерных компьютеров) может варьироваться от 1 до 64 +.

Теперь я перечислю ситуации, которые могут вызвать этот диапазон:

Оптимальные потоки <количество ядер </strong>

В определенных задачах с очень мелкозернистой параллелью (таких как небольшие БПФ) накладные расходы на многопоточность являются доминирующим фактором производительности. В некоторых случаях не стоит распараллеливать вообще. В некоторых случаях вы получаете ускорение с 2 потоками, но при обратном масштабировании на 4 потока.

Другая проблема - конфликт ресурсов. Даже если у вас есть задача с высокой степенью распараллеливания, которую можно легко разделить на 4 ядра / потоки, вы можете оказаться в узком месте из-за пропускной способности памяти и эффектов кэша. Очень часто вы обнаружите, что 2 потока будут такими же быстрыми, как 4 потока. (как часто бывает с очень большими БПФ)

Оптимальные потоки = количество ядер

Это оптимальный случай. Не нужно объяснять здесь - один поток на ядро. Большинство смущающих параллельных приложений, которые не связаны с памятью или вводом-выводом, подходят именно здесь.

Оптимальные потоки> Количество ядер

Вот тут становится интересно ... очень интересно. Вы слышали о дисбалансе нагрузки? Как насчет чрезмерного разложения и кражи работы?

Многие распараллеливаемые приложения нерегулярны - это означает, что задачи не разбиваются на подзадачи одинакового размера. Так что, если вы можете разделить большую задачу на 4 неравных размера, назначьте их на 4 потока и запустите на 4 ядрах ... результат? Плохая параллельная производительность, потому что 1 поток получил в 10 раз больше работы, чем другие потоки.

Распространенным решением здесь является чрезмерное разложение задачи на множество подзадач. Вы можете создавать потоки для каждого из них (так что теперь вы получаете threads >> cores ). Или вы можете использовать какой-нибудь планировщик задач с фиксированным числом потоков. Не все задачи подходят для обоих, поэтому довольно часто подход чрезмерного разбиения задачи на 8 или 16 потоков для 4-ядерного компьютера дает оптимальные результаты.


Хотя порождение большего количества потоков может привести к лучшему распределению нагрузки, накладные расходы возрастают. Так что обычно где-то есть оптимальная точка. Я видел до 64 потоков на 4 ядрах. Но, как уже упоминалось, это сильно зависит от приложения. И тебе нужно поэкспериментировать.


РЕДАКТИРОВАТЬ: Расширение ответа для более прямого ответа на вопрос ...

Сколько стоит переключение контекста? Время для хранения и восстановления Регистры процессора для другого контекста?

Это очень зависит от окружающей среды - и его довольно сложно измерить напрямую.
Краткий ответ: Очень дорого Это может быть хорошим чтением.

А как насчет кешей, конвейеров и различных вещей с предсказанием кода внутри? ЦПУ? Можем ли мы сказать, что каждый раз, когда мы меняем контекст, мы повреждаем кэши, конвейеры и некоторые средства декодирования кода в CPU?

Краткий ответ: Да Когда вы переключаете контекст, вы, вероятно, очищаете свой конвейер и путаете все предикторы. То же самое с кешами. Новый поток, скорее всего, заменит кеш новыми данными.

Хотя есть одна загвоздка. В некоторых приложениях, где потоки совместно используют одни и те же данные, возможно, что один поток потенциально может «подогреть» кэш для другого входящего потока или другого потока в другом ядре, совместно использующих тот же кэш. (Хотя это случалось редко, я уже видел это раньше на одной из моих машин NUMA - суперлинейное ускорение: 17,6x на 16 ядер!?!?!)

То есть больше потоков, выполняющихся на одном ядре, меньше работы, которую они могут выполнять вместе, по сравнению с их последовательным выполнением?

Зависит, зависит ... Помимо гиперпоточности, определенно будут накладные расходы.Но я читал статью, в которой кто-то использовал вторую ветку для предварительной выборки основной ветки ... Да, это безумие ...

0 голосов
/ 08 февраля 2012

4 потока быстрее, если вы можете программировать переключение 40 задач лучше, чем операционная система.

0 голосов
/ 08 февраля 2012

Создание 50 потоков на самом деле повредит производительности, а не улучшит ее. Это просто не имеет никакого смысла.

В идеале вы должны сделать 4 темы, не больше, не меньше. Из-за переключения контекста будут некоторые накладные расходы, но это неизбежно. Потоки ОС / сервисов / других приложений тоже должны выполняться. Но в настоящее время с такими мощными и быстродействующими ЦП это не имеет значения, поскольку потоки этих ОС будут занимать менее 2% времени ЦП. Почти все они будут в заблокированном состоянии во время работы вашей программы.

Вы можете подумать, что, поскольку производительность имеет решающее значение, вам следует кодировать эти небольшие критические области на языке ассемблера низкого уровня. Современные языки программирования позволяют это.

А если серьезно ... компиляторы и, в случае Java, JVM, оптимизируют эти части настолько хорошо, что это просто не стоит (если вы на самом деле не хотите использовать что-то подобное). Вместо того, чтобы ваши вычисления заканчивались через 100 секунд, они заканчивались через 97 или 98. Вопрос, который вы должны задать себе: стоит ли все эти часы кодирования и отладки?

Вы спрашивали о временных затратах на переключение контекста. В эти дни они чрезвычайно низки. Посмотрите на современные двухъядерные процессоры, работающие под управлением Windows 7, например. Если вы запустите веб-сервер Apache на этом компьютере и сервер базы данных MySQL, вы легко перейдете более 800 потоков. Машина просто этого не чувствует. Чтобы увидеть, насколько низка эта стоимость, прочитайте здесь: Как оценить издержки переключения контекста потока? . Чтобы избавить вас от части поиска / чтения: переключение контекста может быть сделано сотни тысяч раз в секунду .

0 голосов
/ 08 февраля 2012

Существует технология Hyperthreading, которая может обрабатывать более одного потока на процессор, но вряд ли зависит от типа вычислений, которые вы хотите сделать. Подумайте об использовании графического процессора или очень низкого языка ассемблера для достижения максимальной мощности.

0 голосов
/ 08 февраля 2012

Если вы можете использовать 4 темы, используйте их.Нет никакого способа, которым 50 пойдет быстрее, чем 4 на 4-ядерном компьютере.Все, что вы получаете, это больше накладных расходов.

Конечно, вы описываете идеальную нереальную ситуацию, поэтому что бы вы ни создавали, вам нужно измерить, чтобы понять, как производительностьпострадавших.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...