Организация взаимодействия между процессами при параллельных вычислениях
В идеальной многозадачной системе все процессы, выполняющиеся параллельно, независимы друг от друга (т.е., асинхронны). На практике такая ситуация маловероятна, поскольку рано или поздно возникают ситуации, когда параллельным процессам необходим доступ к некоторым общим ресурсам. Для этого необходимо введение (на уровне ОС или библиотек) средств, предоставляющих такую возможность.
Параллелизация программы - это задача для разработчика, намного по сложности превосходящая программирование классическое. Для начала программист должен решить, какие части программы могут выполняться одновременно, какую схему параллелизации выбрать, и как эти фрагменты будут взаимодействовать. Одна из самых сложных проблем при разработке параллельных программ - это отладка. Дело в том, что два раза запустив программу в таком режиме, можно получить разные результаты. Просто фрагменты кодов, выполняющиеся независимо, могут выполняться с разной скоростью, в зависимости от того, кто получил больше времени от операционной системы.
Итак, как же может выполняться распараллеливание задачи?
Мы имеем некоторую вычислительную задачу (например, суммирование числового ряда) и хотим ускорить время ее вычисления. Если применить распараллеливание задачи, то мы должны получить вместо одного вычислительного процесса несколько, каждый из который будет решать свою подзадачу (например, производить суммирование на определенном диапазоне). Как это происходит? Есть главный процесс и подчиненные ему процессы. Каждый процесс идентифицируется своим номером (рангом). Вначале главный процесс должен сообщить каждому из подчиненных, какую часть задачи тот должен делать, после чего все процессы начинают выполнять вычисления. Заметим, что результаты у всех процессов могут получиться в разное время, т.е. асинхронно. После того, как все процессы выполнят свои вычисления, они должны отдать результаты своих вычислений главному процессу, затем главный процесс выполняет обработку результатов и получает ответ. Так выглядит распараллеливание задачи. Приведенный выше пример может быть реализован несколькими способами, в зависимости от доступных операций передачи сообщений между процессами. Процессы обмениваются данными между собой при помощи функций передачи сообщений – все эти функции находятся внутри параллельной библиотеки или операционной системы и предоставлены разработчику параллельных программ.
Для сбора результата главный процесс может применять к каждому процессу операцию синхронного получения результата, т.е. обращаться в цикле к каждому процессу в отдельности. У этого подхода есть очевидный минус – мы не сможем получить результат от второго процесса до тех пор, пока не получим от первого, так как будет происходить блокировка. Можно избежать этого – применить не блокирующую (асинхронную) функцию получения результата, тогда нам не придется ждать, пока первый процесс выдаст ответ, чтобы обратиться ко второму и т.д., но придется применить барьерную синхронизацию для всех процессов, чтобы узнать, когда все результаты будут получены. Такой подход эффективнее, но его сложнее реализовать и отладить. И наконец, есть третье решение – главный процесс вызывает функцию коллективной коммуникации – она получает данные синхронно и одновременно от всех процессов и отдает их вызвавшему ее (главному) процессу. Очевидно, что это наиболее удобный подход при условии, что число подчиненных процессов более одного.
Для решения этой задачи мы применяли различные функции обмена сообщениями, они являются стандартными для параллельных библиотек, и являются далеко не пределом возможностей для передачи сообщений для таких библиотек. Во многом написание параллельных программ и строится на грамотном выборе механизмов взаимодействия процессов, о них и идет речь в данном пособии. Такие механизмы можно классифицировать следующим образом – взаимодействия точка-точка, коллективные взаимодействия и синхронизация.
Дата добавления: 2016-05-31; просмотров: 1434;