Сообщество Engee

Параллельные вычисления

Автор
avatar-maximsidorovmaximsidorov
Notebook

Параллельные вычисления в языке Julia

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

Введение

Что такое параллельные вычисления?

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

Этот подход часто используется для:

  • Оптимизации производительности
  • Обработки множества задач одновременно
  • Работы с сетевыми запросами или I/O операциями

Основная часть

Создаем массив слов, которые будем выводить асинхронно

words = ["Julia", "лучший", "язык", "программирования"]
4-element Vector{String}:
 "Julia"
 "лучший"
 "язык"
 "программирования"

Создаем функцию, которая будет срабатывать каждые случайное количество секунд

function sleepprint(s)
    # Генерируем задержку от 0 до 1 секунды (по умолчанию)
    sleep(rand())
    # Выводим строку в консоль
    println(s)
end
sleepprint (generic function with 1 method)

Интересный момент здесь – использование двух макросов:

  • @async запускает задачу асинхронно в фоновом режиме.
  • @sync гарантирует, что основной процесс дождётся завершения всех асинхронных задач, прежде чем продолжит выполнение.

Следующий цикл запускает каждое слово из списка в отдельной задаче (Task) через вызов функции sleepprint.

# Запускаем все асинхронные задачи по пять раз:
for i in 1:5
    println("\nИтерация №: $i")
    
    @sync for word in words
        # Для каждой итерации создаём async задачу
        @async sleepprint(word)
    end
end
Итерация №: 1
лучший
Julia
программирования
язык

Итерация №: 2
язык
программирования
лучший
Julia

Итерация №: 3
язык
программирования
Julia
лучший

Итерация №: 4
язык
Julia
лучший
программирования

Итерация №: 5
язык
программирования
Julia
лучший

Поскольку sleep(rand()) генерирует разные временные интервалы, порядок вывода строк может меняться при каждом запуске скрипта.

Принцип работы следующий:

  1. Мы говорим @sync, что хотим дождаться окончания всех действий внутри блока;
  2. Затем для каждого слова создаётся независимая @async задача, которая запустит sleepprint;
  3. Поскольку sleep(rand()) делает паузу по разным причинам, выполнение задач происходит «вразброс»;
  4. Но благодаря @sync, главное поток продолжает работать только после завершения ВСЕХ таких задач.

Заключение

Мы рассмотрели простую демонстрацию параллельных вычислений на языке Julia. С помощью макросов@async и @sync мы смогли организовать конкурентное выполнение функции sleepprint, которая имитировала некую длительную работу (искусственная задержка).

Это показывает, как легко можно распараллеливать простейшие задачи в Julia без необходимости использовать внешние библиотеки. Такой метод подходит для ситуаций, где необходимо выполнить несколько независимых операций (например, обращения к базе данных, чтение файлов, API-вызовы) более эффективно, чем последовательно, особенно если эти операции требуют ожидания внешних ресурсов.

Пример разработан с использованием материалов Rosetta Code