Как человеку из мира HPC, пришедшему из мира корпоративной веб-разработки, мне всегда любопытно посмотреть, как разработчики «в реальном мире» используют преимущества параллельных вычислений. Сейчас это гораздо более актуально, чем все чипы станут многоядерными, и будет еще более актуальным, когда на чипе тысячи ядер, а не всего несколько.
Мои вопросы:
Наконец, я сформулировал это как многоядерный вопрос, но не стесняйтесь говорить о других типах параллельных вычислений. Если вы переносите часть своего приложения для использования Уменьшение карты, или если MPI на больших кластерах является для вас парадигмой, то обязательно упомяните и об этом.
Обновлять: Если вы ответите на # 5, укажите, думаете ли вы, что все изменится, если будет больше ядер (100, 1000 и т. д.), Чем вы можете кормить с доступной пропускной способностью памяти (видя, как пропускная способность становится все меньше и меньше на ядро) . Можете ли вы по-прежнему использовать оставшиеся ядра для своего приложения?





for → Parallel.For и тому подобным. Я работаю в области медицинской визуализации и обработки изображений.
Мы обрабатываем несколько ядер почти так же, как и одноядерные: у нас уже есть несколько потоков в приложениях, которые мы пишем, чтобы иметь отзывчивый пользовательский интерфейс.
Однако, поскольку теперь это возможно, мы внимательно следим за реализацией большинства наших операций обработки изображений в CUDA или OpenMP. Компилятор Intel предоставляет много хороших примеров кода для OpenMP и является гораздо более зрелым продуктом, чем CUDA, и обеспечивает гораздо большую установленную базу, так что мы, вероятно, собираемся пойти на это.
Что мы обычно делаем для дорогостоящих (т. Е. Более секунды) операций, так это по возможности переложить эту операцию на другой процесс. Таким образом, основной пользовательский интерфейс остается отзывчивым. Если мы не можем, или просто слишком неудобно или медленно перемещать такой объем памяти, операция все еще выполняется в потоке, и тогда эта операция сама может порождать несколько потоков.
Ключ для нас - убедиться, что мы не столкнемся с узкими местами параллелизма. Мы разрабатываем в .NET, а это означает, что обновления пользовательского интерфейса должны выполняться с помощью вызова Invoke пользовательского интерфейса, чтобы основной поток обновлял пользовательский интерфейс.
Может быть, я ленив, но на самом деле я не хочу тратить слишком много времени на выяснение многих вещей, когда дело доходит до распараллеливания таких вещей, как инверсия матриц и тому подобное. Многие действительно умные люди потратили много времени на то, чтобы делать это быстро, как закись азота, и я просто хочу взять то, что они сделали, и назвать это. Что-то вроде CUDA имеет интересный интерфейс для обработки изображений (конечно, для этого он определен), но он все еще слишком незрелый для такого рода программирования plug-and-play. Если у меня или у другого разработчика будет много свободного времени, мы можем попробовать. Поэтому вместо этого мы просто воспользуемся OpenMP, чтобы ускорить нашу обработку (и это определенно входит в план разработки на следующие несколько месяцев).
Это выглядит очень интересно. Я работаю в Windows, но если компилятор можно перенести, я бы точно не работал.
Я считаю, что они подходят для Windows - PGI включен в это: microsoft.com/hpc/en/us/developer-resources.aspx, хотя упоминается только Фортран. Но на сайте PGI упоминается версия 8.0 для Windows здесь: pgroup.com/support/install.htm#win_info. Однако я этого не пробовал.
Я занимаюсь обработкой изображений. Мы используем многоядерность там, где это возможно, обрабатывая изображения в срезах, распределенных по разным потокам.
Привет! У меня сейчас похожая проблема, не могли бы вы взглянуть? :) stackoverflow.com/questions/973608/fast-interleaving-of-data
Я сделал это тоже для аналогичного приложения. Разделение изображения на количество частей, равное количеству доступных ядер. Для двухъядерной машины я получил прирост производительности на 15% за счет разделения изображения пополам и использования потока для каждого для выполнения работы.
@Andrei - В книге «Многопоточное программирование на C# 2008 и 2005» есть пример приложения, которое делает то же самое. Это может быть хорошей ссылкой для сравнения с вашим решением.
Моя дипломная работа заключается в разработке концепций многоядерной работы с голым железом и обучении во встроенных системах.
Я также немного работаю с F#, чтобы ускорить работу моих высокоуровневых многопроцессорных языковых средств.
Я разрабатываю веб-приложения ASP.NET. Существует небольшая возможность использовать многоядерность непосредственно в моем коде, однако IIS уже хорошо масштабируется для нескольких ядер / ЦП, порождая несколько рабочих потоков / процессов под нагрузкой.
Верно для любой веб-среды.
Для веб-приложений это очень и очень просто: игнорируйте это. Если у вас нет кода, который действительно требует параллельной работы, вы можете просто написать однопоточный код в старом стиле и быть счастливым.
Обычно в любой момент времени нужно обрабатывать гораздо больше запросов, чем ядер. И поскольку каждый из них обрабатывается в своем собственном потоке (или даже в процессе, в зависимости от вашей технологии), это уже работает параллельно.
Единственное, где вам нужно быть осторожным, - это доступ к какому-то глобальному состоянию, требующему синхронизации. Сведите это к минимуму, чтобы избежать создания искусственных узких мест в мире (почти) идеально масштабируемом.
Итак, для меня многоядерность в основном сводится к следующим элементам:
Хороший ответ. Как насчет вопроса о долгосрочной масштабируемости? Ожидаете ли вы, что вам придется что-то менять, если у вас появится больше ядер на чипе, чем вы можете накормить? С 1000 ядрами у вас может не хватить пропускной способности памяти для всех этих запросов. Остальные ядра еще можно использовать?
В той области, в которой я работаю в основном (веб-приложения, которые в основном связаны с базой данных со случайной логикой), я не ожидаю, что мне понадобится изменить это в обозримом будущем (но такие прогнозы, как известно, ошибочны), поскольку их основные узким местом обычно является БД и ничего больше.
При этом есть части (пакетная обработка, редкая часть, связанная с процессором), где написание хорошего многопоточного кода определенно может помочь, и здесь я сталкиваюсь почти с теми же проблемами / решениями, что и все остальные.
Важно отметить, что Apache даже не использует потоки внутри. Он просто порождает новые процессы для обработки дополнительных запросов.
Нолти: если вы используете поток для каждого запроса или процесс, в этом контексте не имеет особого значения. Идея та же.
На самом деле, информация о том, что Apache не использует потоки, на данный момент устарела.
Логика нашей предметной области в значительной степени основана на механизме рабочего процесса, и каждый экземпляр рабочего процесса запускается из ThreadPool.
Для нас этого достаточно.
Теперь я могу отделить свою основную операционную систему от разработки / установки того, что мне нравится, используя настройки витуализации с помощью Virtual PC или VMWare.
Двухъядерный означает, что на одном процессоре работает моя основная ОС, а на другом - моя ОС для разработки с приличным уровнем производительности.
Моя исследовательская работа включает работу над компиляторами и фильтрацией спама. Я также много занимаюсь «личной продуктивностью» Unix. Кроме того, я пишу и использую программное обеспечение для администрирования классов, которые я преподаю, включая выставление оценок, тестирование кода учащихся, отслеживание оценок и множество других мелочей.
Резюме (которое я услышал от основного докладчика, который работает на ведущего производителя процессоров): индустрия поддержала многоядерность, потому что они не могли заставить машины работать быстрее и горячее, и они не знали, что делать с дополнительными транзисторами. Теперь они отчаянно пытаются найти способ сделать многоядерные системы прибыльными, потому что, если у них нет прибыли, они не смогут построить производственные линии следующего поколения. Соус закончился, и нам, возможно, действительно придется обратить внимание на стоимость программного обеспечения.
Многие люди, серьезно относящиеся к параллелизму, игнорируют эти игрушечные 4-ядерные или даже 32-ядерные машины в пользу графических процессоров со 128 процессорами или более. Я предполагаю, что настоящие действия будут там.
Я не думаю, что игнорирование параллелизма намеренно - это хороший подход, особенно когда совершенно ясно, что тенденция - все больше и больше ядер. Кроме того, модели программирования становятся проще, например, с помощью PLINQ и Intel Parallel Studio.
За эти годы я сэкономил сотни, если не тысячи часов, игнорируя параллелизм. Параллелизм существует, чтобы служить мне; А не наоборот. В прошлом месяце, когда мне нужно было протестировать 30 долгосрочных студенческих программ, я с радостью использовал 30 ядер, распределенных на 15 машинах, но это было редкостью.
По состоянию на 2014 год это все еще в целом верно (и я один из тех чудаков, которые часто используют Erlang, не меньше). Большинство клиентского программного обеспечения, которое я пишу, не требует ничего, кроме одного потока. Дополнения ортогональных функций часто лучше всего работают как дополнительные программы, которые могут взаимодействовать с другими / исходными программами. За меня этим занимается ОС. С практической точки зрения, многоядерность в контексте решения клиентских проблем в бизнес-вычислениях означает запрет Firefox, Flash или программе просмотра документов блокировать бухгалтерское приложение или программу САПР. На стороне сервера все меняется, но это не код наиболее.
Пока что не более чем более эффективная компиляция с make:
gmake -j
опция -j позволяет выполнять задачи, которые не зависят друг от друга, параллельно.
Изучение функционального языка программирования может потребовать использования нескольких ядер ... дорого.
Я думаю, что использовать дополнительные ядра не так уж и сложно. Существуют некоторые мелочи, связанные с веб-приложениями, которые не нуждаются в дополнительной заботе, поскольку веб-сервер выполняет свою работу, параллельно выполняя запросы. Вопросы относятся к долгосрочным алгоритмам (длинные - это то, что вы называете длинными). Их необходимо разделить на более мелкие домены, которые не зависят друг от друга, или синхронизировать зависимости. Многие алгоритмы могут это сделать, но иногда требуются ужасно разные реализации (опять же затраты).
Так что никакой серебряной пули, пока вы не используете императивные языки программирования, извините. Либо вам нужны квалифицированные программисты (дорого), либо вам нужно обратиться к другому языку программирования (дорого). Или вам может просто повезти (Интернет).
Я работаю на C# с .Net Threads. Вы можете комбинировать объектно-ориентированную инкапсуляцию с управлением потоками.
Я прочитал несколько сообщений от Питера о новой книге от Packt Publishing, и я нашел следующую статью на веб-странице Packt Publishing:
http://www.packtpub.com/article/simplifying-parallelism-complexity-c-sharp
Я прочитал книгу Джо Даффи «Параллельное программирование с Windows». Теперь жду "Потоковое программирование на C# 2008 и 2005", книгу Хиллара - http://www.amazon.com/2008-2005-Threaded-Programming-Beginners/dp/1847197108/ref=pd_rhf_p_t_2
Я согласен с Szundi: "Серебряной пули нет"!
Вы говорите: «Для веб-приложений это очень, очень просто: игнорируйте это. Если у вас нет кода, который действительно требует выполнения параллельно, вы можете просто написать однопоточный код старого стиля и быть счастливым».
Я работаю с веб-приложениями, и мне нужно в полной мере использовать преимущества параллелизма. Я понимаю вашу точку зрения. Однако мы должны подготовиться к многоядерной революции. Игнорировать это то же самое, что игнорировать революцию GUI в 90-х.
Мы еще не разрабатываем под DOS? Мы должны заняться многоядерностью, иначе мы умрем через много лет.
Мы создает анализатор кода VivaMP для обнаружения ошибок в параллельных программах OpenMP.
VivaMP - подобный линту статический анализатор кода C / C++, предназначенный для выявления ошибок в параллельных программах, основанных на технологии OpenMP. Статический анализатор VivaMP значительно расширяет возможности существующих компиляторов, диагностирует любой параллельный код, в котором есть ошибки или который может быть источником таких ошибок. Анализатор интегрирован в среду разработки VisualStudio2005 / 2008.
Я сказал кое-что из этого в ответ на другой вопрос (надеюсь, все в порядке!): Существует концепция / методология под названием Программирование на основе потоков (FBP), которая существует уже более 30 лет и используется для обработки большей части пакетной обработки. в крупном канадском банке. Он имеет реализации на основе потоков в Java и C#, хотя более ранние реализации были основаны на волокне (C++ и Assembler для мэйнфреймов). Большинство подходов к проблеме использования преимуществ многоядерности включают попытку взять обычную однопоточную программу и выяснить, какие части могут работать параллельно. FBP использует другой подход: приложение с самого начала спроектировано с точки зрения нескольких компонентов «черного ящика», работающих асинхронно (подумайте о производственной сборочной линии). Поскольку интерфейс между компонентами представляет собой потоки данных, FBP по существу не зависит от языка и, следовательно, поддерживает многоязыковые приложения и языки, специфичные для предметной области. Приложения, написанные таким образом, оказались более удобными в обслуживании, чем обычные однопоточные приложения, и часто занимают меньше времени даже на одноядерных машинах.
Я считаю, что "Циклы - лучший друг инженеров".
Моя компания предоставляет коммерческий инструмент для анализа и трансформируется очень большие программные системы на многих компьютерных языках. «Большой» означает 10-30 миллионов строк кода. Инструмент представляет собой набор инструментов для реинжиниринга программного обеспечения DMS. (Сокращенно DMS).
Анализирует (и даже трансформирует) в таких огромных системах займет много времени: наш анализатор точек для C код занимает 90 часов ЦП на x86-64 с 16 ГБ ОЗУ. Инженеры хотят получить ответы быстрее.
Следовательно, мы реализовали DMS в ПАРЛАНС, язык параллельного программирования собственной разработки, предназначенный для использования мелкомасштабных многоядерных разделяемых системы памяти.
Ключевые идеи parlanse: а) позволить программисту раскрыть параллелизм, б) позволить компилятору выбрать, какую часть он может реализовать, c) свести переключение контекста к абсолютному минимуму. Статические частичные порядки над вычислениями равны легко помочь достичь всех 3; Легко сказать, относительно легко измерить затраты, компилятору легко планировать вычисления. (Написание параллельной быстрой сортировки с этим тривиально).
К сожалению, мы сделали это в 1996 году :-( Последние несколько лет наконец стали оправданием; Теперь я могу купить 8 ядерных машин в Fry's менее чем за 1 тысячу долларов. и 24 основных машины примерно по той же цене, что и небольшой автомобиль (и, вероятно, быстро упадет).
Хорошая новость в том, что DMS сейчас достаточно зрелая, и есть ряд ключевых внутренних механизмов в DMS, которые используют это преимущество, в частности целый класс анализаторов называют "грамматиками атрибутов", который мы пишем на предметно-ориентированном языке что НЕ является обычным явлением. DMS компилирует эти передают грамматики в PARLANSE, а затем выполняются параллельно. Наш фронт на C++ end использует грамматику атрибутов и составляет около 100 КБ sloc; он скомпилирован в 800K SLOC параллельного код Parlanse, который действительно работает надежно.
Сейчас (июнь 2009 г.) мы очень заняты тем, чтобы сделать DMS полезной, и не всегда хватает времени, чтобы использовать параллелизм Что ж. Таким образом, 90 часов указывает на анализ. Мы работаем над распараллеливанием этого, и есть разумные надежды на ускорение в 10-20 раз.
Мы считаем, что в конечном итоге использование SMP хорошо сделает рабочие станции намного больше дружелюбны к инженерам, задающим сложные вопросы. И они должны.
Я думаю, что эта тенденция сначала убедит некоторых разработчиков, а затем большинство из них увидят, что распараллеливание - действительно сложная задача. Я ожидаю, что придет какой-то шаблон проектирования, который позаботится об этой сложности. Не низкоуровневые, а архитектурные шаблоны, которые усложнят ошибку.
Например, я ожидаю, что шаблоны обмена сообщениями станут популярными, потому что они по своей сути асинхронны, но вы не думаете о тупиках, мьютексах и т. д.
Я использую и программирую на Mac. Grand Central Dispatch для победы. В обзоре Snow Leopard Ars Technica есть много интересного, что можно сказать о многоядерном программировании и о том, что люди (или, по крайней мере, Apple) идут с этим.
Я решил использовать преимущества нескольких ядер в реализации алгоритма ВЫПУСКАТЬ. MArc Adler сделал нечто подобное в коде C с помощью PIGZ (параллельный gzip). Я поставил философский эквивалент, но в библиотеке управляемого кода, в DotNetZip v1.9. Это не порт PIGZ, а похожая идея, реализованная самостоятельно.
Идея DEFLATE состоит в том, чтобы сканировать блок данных, искать повторяющиеся последовательности, создавать «словарь», который отображает короткий «код» на каждую из этих повторяющихся последовательностей, а затем генерировать поток байтов, в котором каждый экземпляр одной из повторяющихся последовательностей заменяется «кодом» из словаря.
Поскольку создание словаря требует больших ресурсов процессора, DEFLATE - идеальный кандидат для распараллеливания. Я использовал подход типа Map + Reduce, при котором я разделяю входящий несжатый bytestreeam на набор меньших блоков (map), скажем, по 64 КБ каждый, а затем сжимаю их независимо. Затем объединяю полученные блоки вместе (уменьшаю). Каждый блок размером 64 КБ сжимается независимо, в своем собственном потоке, без учета других блоков.
На двухъядерном компьютере этот подход сжимается примерно в 54% времени по сравнению с традиционным последовательным подходом. На машинах серверного класса с большим количеством доступных ядер он потенциально может обеспечить даже лучшие результаты; без сервера, я не тестировал его лично, но люди говорят мне, что он быстрый.
Существуют накладные расходы времени выполнения (ЦП), связанные с управлением несколькими потоками, накладные расходы памяти времени выполнения, связанные с буферами для каждой темы, и накладные расходы данных, связанные с объединением блоков. Таким образом, этот подход окупается только для больших байтовых потоков. В моих тестах выше 512к может окупиться. Ниже этого лучше использовать последовательный подход.
DotNetZip поставляется в виде библиотеки. Моей целью было сделать все это прозрачным. Таким образом, библиотека автоматически использует дополнительные потоки, когда размер буфера превышает 512 КБ. Приложению ничего не нужно делать, чтобы использовать потоки. Это просто работает, а когда используются потоки, это волшебно быстрее. Я думаю, что это разумный подход для большинства библиотек, используемых приложениями.
Было бы неплохо, если бы компьютер уметь автоматически и динамически использовать ресурсы с помощью параллелизируемых алгоритмов, но реальность такова, что разработчики приложений должны явно кодировать распараллеливание в.
Как это повлияет на ваш план развития программного обеспечения?
Это не так. Наши (как и почти все другие) бизнес-приложения отлично работают на одном ядре. Мы счастливы, если добавление дополнительных ядер не приведет к значительному снижению производительности однопоточных приложений.
... реальные истории ...
Как и все остальные, основное преимущество, которое мы получаем, - это параллельные сборки. Компилятор Visual Studio 2008 C#, похоже, не использует более одного ядра, что действительно отстой.
Что вы делаете со своим существующим кодом, чтобы воспользоваться преимуществами многоядерных машин
Мы можем рассмотреть возможность использования параллельных расширений .NET, если у нас когда-либо будет длительный алгоритм, который можно распараллелить, но шансы на то, что это действительно произойдет, невелики. Наиболее вероятный ответ заключается в том, что некоторые разработчики будут экспериментировать с ним ради интереса, но не более того.
как вы будете иметь дело с сотнями или тысячами ядер?
Голова -> Песок.
Если вашему домену не так легко добиться преимуществ от параллельных вычислений, то тоже интересно объяснить, почему.
Клиентское приложение в основном передает данные, серверное приложение в основном полагается на SQL-сервер, который выполняет тяжелую работу.
Мы добились больших успехов в параллелизме задач в .NET 4 с использованием F#. Наши клиенты нуждаются в поддержке многоядерных процессоров, потому что они не хотят, чтобы их ядра n-1 простаивали!
Я пользуюсь преимуществом многоядерности с использованием C, PThreads и домашней реализации взаимодействия последовательных процессов на платформе OpenVPX с Linux с использованием планировщика набора исправлений PREEMPT_RT. Все это приводит к почти 100% загрузке ЦП в нескольких экземплярах ОС без использования процессорного времени для обмена данными между картами процессоров в шасси OpenVPX, а также с очень низкой задержкой. Также используется sFPDP для объединения нескольких шасси OpenVPX в одну машину. Я не использую внутренний DMA Xeon, чтобы уменьшить давление на память внутри ЦП (DMA по-прежнему использует пропускную способность памяти за счет ядер ЦП). Вместо этого мы оставляем данные на месте и передаем право собственности на них с помощью CSP (что мало чем отличается от философии библиотеки параллельных потоков данных .NET).
1) Дорожная карта программного обеспечения - у нас есть давление, чтобы максимально использовать недвижимость и доступную мощность. Очень важно максимально использовать новейшее оборудование
2) Область программного обеспечения - по сути, научные вычисления
3) Что мы делаем с существующим кодом? Постоянно разбивая его на части и перераспределяя его части по потокам, чтобы каждое ядро было максимально загружено, делая все возможное, не нарушая требований реального времени. Новое оборудование требует значительного переосмысления (более быстрые ядра могут делать больше за заданное время, не хотят, чтобы они использовались недостаточно). Не так плохо, как кажется - основные процедуры очень модульные, поэтому их легко собрать в куски размером с резьбу. Хотя мы планировали взять под контроль сходство потоков у Linux, нам пока не удалось добиться значительного увеличения производительности, сделав это. Linux довольно хорош в получении данных и кода в более или менее одном и том же месте.
4) Фактически уже есть - общая машина уже складывает до тысяч ядер
5) Параллельные вычисления необходимы - это система MISD.
Если это звучит как большая работа, это так. некоторые работы требуют полной отдачи, чтобы максимально использовать доступное оборудование и избегать почти всего, что является высокоуровневым. Мы обнаружили, что общая производительность компьютера зависит от пропускной способности памяти ЦП, а не от частоты ядра ЦП и размера кеш-памяти L1 / L2 / L3.
Спасибо за хороший ответ. Вы видели последние компиляторы Portland Group? Сейчас это всего лишь предварительный просмотр, но у них есть предварительная поддержка автоматического ускорения с использованием CUDA: pgroup.com/resources/accel.htm